Charles Max_Wood:
Hey, welcome back to Ruby. Rogues This week On our panel we have Valentino stoll.
Valentino_Stoll:
Hey, now,
Charles Max_Wood:
I'm Charles, Max Wood from top end devs, and this week we have a special guest. that is Alex Evanczuk. I hope I said that right.
Alex_Evanczuk
You. Got it?
Charles Max_Wood:
Yeah, with all the technical difficulties I'm like. Oh, I forgot what he said anyway. Do you want to tell people real quick why you're famous and exciting to talk to?
Alex_Evanczuk
Uh? sure, yeah, so not so much Sure about famous and exciting, but I'm Alex and I work on the product infrastructure team at Gusto, which you know we call ourselves the only one people platform. Gusto offers pay roll benefits, H, r, and
Charles Max_Wood:
Ah,
Alex_Evanczuk
a bunch of
Charles Max_Wood:
cool.
Alex_Evanczuk
other stuff to small and large businesses, And at gusto, I work on a lot of different product infrastructure, kind of things. But my main focus for the past two years, So has been around product modularization.
Charles Max_Wood:
Nice, Um, I think that kind of ties into what we're talking about today because we ran across your article came out in January. It says how how to guide for Ruby packs, gusts, jemmicosystem for modulizing Ruby applications, And I started looking through this and you know, because I was like Ruby packs, I had really heard of ruby packs, and you know, maybe this is something that I just haven't had the opportunity to use. I don't know if it's a well established thing out there that I didn't see, but Looks like it's just a gem that includes a bunch of functionality. Why don't you just tell me what I got wrong, as far as what it is like, What is a pack? And
Alex_Evanczuk
Sure,
Charles Max_Wood:
what do you use it for?
Alex_Evanczuk
yeah, yeah, now nothing. nothing you got wrong, You now pack is, Packs are a new concept of something that Gusto and myself are trying to necessarily popular. Ise don't necessarily care if it's popular Perse, but we want to try to solve problems around Ruby modularization
Charles Max_Wood:
Uh
Alex_Evanczuk
and
Charles Max_Wood:
huh,
Alex_Evanczuk
just to back up for a second. You know a lot of us are familiar with Gems, which is the Ruby communities, Salt Ion for Uh, packaging and distributing Ruby code. The thing
Charles Max_Wood:
Right,
Alex_Evanczuk
with gems is that in order for something to be a gem, it has to have uh, technically perfect boundaries, And by that, I mean you have to be very strict about your dependencies. You can only reference things that are within your gem or within your dependencies. Now this is where it made it really hard to use gems in an existing application yet, Such as Gustus, Gusta's
Charles Max_Wood:
Uh,
Alex_Evanczuk
application,
Charles Max_Wood:
huh,
Alex_Evanczuk
was as big and tangled monolyth with aspirational boundaries. You know, we had a lot of things we thought should be, maybe in a gym here there, but it was all entangled like any real organic system. So packs are kind of like a light weight gem. To do something that we call gradual modularization. You can basically put things in a pack and then use this other Eco system of tools, too, Uh, I, to kind of give you a temple, to, kind of give you some guidance to arrive at those boundaries within the code base.
Charles Max_Wood:
Okay, so I'm kind of imagining a couple of different ways this could go right, and on your blog posts T look like you might get like a pack is a pack around different functionality that all kind of live in the same place like there's a Rube cop pack right. So it in includes extra cops and stuff like that for Rube cop that make it do stuff or things like that. The way you described it, it almost sounded like you also might be packaging up your own code for a lack of a better way to put it, you know, and and creating the boundaries that way, So
Alex_Evanczuk
Yeah,
Charles Max_Wood:
is it one the other or both?
Alex_Evanczuk
Yeah, so so we tend to think of packs first and foremost as a way of drawing domain boundaries around product and business domains, So for example, you know, if you have a large opplication, for example, a gusto, we need to pay people through pay roll. So we, and of course this is all kind of over simplified, but the idea is we might have a pay roll pack And a
Charles Max_Wood:
Okay,
Alex_Evanczuk
payments pack, and you know a company like gusto when you're first starting payments, and pay roll may be inextricably sort of couples. You know, the only time we're paying people is through pay role, but as our software system grows, we find other places we want to you know, pay people in other ways, So we want to start to de couple these systems and to do that we start to create these packs and solidify and improve the boundaries. Betwe, No,
Charles Max_Wood:
I got you, Um, for our book club in January, we read Clean Architecture and Uncle Bob talks about the idea of components and it's kind of the same idea, Right And then of course he gives you permission as your Ap evolves and you kind of brought this up right to find some of those other boundaries right where? Yeah, initially you only had one thing calling the other the other thing. And so they were more or less just one thing. Right Because Was just one set of functionality. But yeah,
Alex_Evanczuk
Yep,
Charles Max_Wood:
now I've got two or three or four other components that rely on this sub set of this one component, so you break it off into another component and that's effectively what you're doing with packs.
Alex_Evanczuk
Yeah, yeah, and you know when when I think about breaking up an application and think about modularizing an application, we're not necessarily doing it for its own sake. You know,
Charles Max_Wood:
M.
Alex_Evanczuk
you know
Charles Max_Wood:
right,
Alex_Evanczuk
clean architecture than the intense of having good. well, modularized architecture is for some business purpose, whether that be to enable other product optionality. You know we want to pay people in
Charles Max_Wood:
Hm,
Alex_Evanczuk
other ways. Maybe it's because there are regulatory or compliance reasons. Maybe it's the code is very confusing and we need to debugget
Charles Max_Wood:
Right.
Alex_Evanczuk
in isolation
Charles Max_Wood:
It's just maintainability here
Alex_Evanczuk
exactly so Yeah and I want to kind of get to the nuts and bolts of packs pack. All it is in its bare bones representation is a folder of code, just a folder with a bunch of Ruby files in it and other files to. And it has a package Gamel at the root of that Older and it doesn't. actually, it doesn't have a bunch of run time components that change much. It's really just about moving code to different places and then using static analysis tools such as pack work to figure out what the boundaries are in the relationship are between those packs between those parts of the system,
Charles Max_Wood:
Before we get too far. I think I heard Valentino in mute, so I'm going to let him ask his question.
Valentino_Stoll:
Yeah, yeah, I've got a lot of questions. I mean my
Charles Max_Wood:
Oh me too.
Valentino_Stoll:
first one. My first one is. I guess mostly around. How is this different than like rails, engines and what made you decide to go in a different direction And I have a feeling that it's more of the shared aspects of this, and I guess that's my follow up is like, kind of uh, what advantages you get out of this new pack packs? You know portion. is it specifically to re use pieces in the modularization, or is it mostly just having the domain knowledge separated?
Alex_Evanczuk
So yeah, Rails engines are great solutions to modulization as well, And that's what gusto started with throughout this whole journey to decompose our monolith. We said. Oh, you know, Rails engines. They are the way, And what we found was a couple of things for Net new projects. Rails engines were worked pretty well for us. You know, They let us put all of our code into one place. Keep it isolated. But what if we have an existing big system And we wanted to pull things into a Rails engine? We might think we tried to pull one file in and run the test on that Rails engine, and realize that that Rails engine depends on a lot of other parts of the system, and as you pull that string, it starts to pull on the entire application. Because a lot of large rails applications, Uh, may be sort of syclicolnature. You know the dependency structure. Everything kind of depends on everything. So rails engines are Are tough because hey don't maybe they don't have this quality of allowing you to adopt them gradually, Whereas with packs you can start to put everything in a pack, and even without those imperfect boundaries you you can use pack work and it will tell you. Hey, you say this thing is in a pack and it doesn't depend on these other packs, but actually hear all the relationships that need to be worked out before you can make this intention, so I like to kind of think of it as potentially a path that that can get you there To an engine. And one other thing I want to add was sometimes if you're working in a Rails engine, you may want to call to an existing system that is not yet an engine you know. Say you have slacknotifier within your application and you need to to hit your slack. A P. It's a post. an important message about the business. Well, the way O do that with Rails engines is either pull that Notify into Rails engine or a gem itself, or to perhaps use dependency injection to pass that into the Rails engine in some way, but with packs, what's nice is that even if you have those perfect boundaries, you can iterate really quickly and perhaps reach outside of that, and you know, provide that business value and come back to architectural or structural improvements when the time permits.
Charles Max_Wood:
That makes sense. One other thing that I'm thinking of is that and and I guess it's a trivial thing because you can just figure it out. but Um, Rails engines, also, Um, you usually mount them under specific route and so you would actually have to change your routing and anything that depended one way or the other. Um, but yeah, I was going to ask the exact same question because I was thinking the same thing. If I need to modularize my rails, Appia, why can't I just put them under engines and then just surface at all? right?
Alex_Evanczuk
Yeah, I mean it's it's It's always worth trying, You know, I think that trying it is
Charles Max_Wood:
Hm,
Alex_Evanczuk
what gave us the experience to realize ends up in really really challenging Because you think about how a gem works, and you know Rails engine is just a gem
Charles Max_Wood:
Right,
Alex_Evanczuk
that connects two rails through rail ties, and other things like that well bundle requires that all of the dependencies within a gems de Ze tree are a sick lick, so
Charles Max_Wood:
Hm,
Alex_Evanczuk
that means that in order to extract something into a gem, you basically either you have to start from the leaf notes. You know, you have to start from the things that depend on nothing. Pull that into the rails engine, and then incrementally, you know, De tangle things until it can fit into the technical requirements of a Rails engine. That's That's a great
Charles Max_Wood:
Right,
Alex_Evanczuk
process. It might lead to really great code with great boundaries, but it will for You potentially go on a sort of a wild goose chase of de tangling things that are not necessarily connected to the types of business value that you want to produce.
Charles Max_Wood:
Yeah, clean architecture also points out some of the dangers of those cyclical relationships both from your entities or classes as well as your components, And so it's an interesting conversation to have as to whether or not, Yeah, having to untangle those things that way may or may not make your code more easy to reason about or things like that, but at the same time, yeah, you're you know. you are forcing a boundary here and that's that's one thing that's nice Is Use. Then you can isolate the system from things that it doesn't. It doesn't need to know about. And you can, you can run those packs on their own. And and that's actually a real nice thing. Because yeah, then if it's a payments pack, you know all I care about is whether or not it'll put the payments through Right Is it? is it making the right A P. I calls across the internet? Um, is it using the right abstraction layer that I put over the top, But that in case the a p, I changes right, And and does it translate the the items in my system correctly to go to the other system? Does it? You know when it receives a response, does it do the right thing? and I don't have to worry about. Does the pay roll system? blah, blah, blah, blah, right, because the pay roll system is in a different pack and it's a different concern. And then then on the other side on the pay roll system, all I really have to do is double check that it's meeting the contract with the pain System on the other end. And so it keeps it relatively simple. So I guess the question is yeah, then what do the packs do Right? How do the packs resolve some of these cyclical dependencies or some of these other issues that you're bringing up with rails, engines that are going to be painful when I try it.
Alex_Evanczuk
Yeah, it's good question, and I'll do my best to to try to answer it. So the way that you know I would recommend or think about this and go about it is first to just think about their their key domains and their mental model for how those domains relate. You know, in case of gusto, we might say Hey, you know, Pay role depends on payments. Payments doesn't depend on pay role, but Payments may rely on Slack. Utility of feature flags, utility authorization, utility, and so on. And then we create those packs. We say Okay, Here's a folder of code called Pay Role. Here's payments, and so on, And then we move the code into those packs, and what we then do is use this tool called Pack Work, which was open source by Shop Fi. And what pack work does Is that it will basically read through all of the pack notes and create edges between those pack notes. That, based on references to Ruby, Constance, so I might say, Oh, you know, I see that payments depends on pay roll here. And what it does is that you can specify the dependencies between packs within the package Am file, so you say Okay, dependencies for payroll Dependencies are payments and feature flags, and so on. And then what pack work does is? It basically takes a diff between the graph that you've declared about how your system should be modelled and the actual graph as it relates to the code base, and that diff basically represents the delta of effort needed to, I guess, actualize the Architecture that you're describing.
Charles Max_Wood:
I'm not sure I completely followed that
Alex_Evanczuk
Sure, Yeah, so
Charles Max_Wood:
and
Alex_Evanczuk
let me,
Charles Max_Wood:
it might just be my brain going.
Alex_Evanczuk
No, No, I don't.
Charles Max_Wood:
It's It's a different idea than what I've done in the past.
Alex_Evanczuk
Yeah. it definitely took me a long time to think about it. You know, first, I, when I first thought about all this, I first heard about pack work. I thought I don't know. I don't. I don't get it. You know we have engines
Charles Max_Wood:
Hm,
Alex_Evanczuk
gems.
Charles Max_Wood:
Right,
Alex_Evanczuk
you know, Ruby has a private constant feature. Why can't I use those? and uh, well, we certainly can use those there. There's still a tool in our tool belt. But when I really liked was when I reflect Back to various times that I tried to extract something into an engine. What I found was that I had a mental model for the final state of that engine. You know all the all the Ap is that it would expose what it would depend on, wouldn't depend on, Et cetera, But that final state that I had had to be represented, I guess in a document and some documentation, I wrote, and sort of tribal knowledge somewhere, and there wasn't a way that Could follow some sort of temple to allow me to get to that stage. So it's what. I. What's really cool about pack work in the idy of packs is that you can basically uh, describe the final state of your system. You can put things into a pack and say, this is what I would like it to depend on. And this is that these are the Apis that I want to expose. And then what pack work will do is it'll say, hear all the places that You have violated your stated dependencies here, all the places where things are using private a pi. So now that process of trying to go from entangled to componentized or modularized, that becomes a sort of mechanized process where you can follow it to, basically produces a todo list where it says Hey, if you do everything on this to do list, you'll be able to turn this into a Rails engine. I'm not sure if that did In clarity. Still trying to work on my pitch a little bit.
Valentino_Stoll:
So it sounds like this is like an elaborate dependency manager.
Alex_Evanczuk
Uh, yeah, maybe I mean you
Valentino_Stoll:
In
Alex_Evanczuk
know.
Valentino_Stoll:
a way, I mean, it does more building than than anything. I think. From what what you're saying, but I'm super curious about the static analysis portion of this. I know that's just
Alex_Evanczuk
Sure,
Valentino_Stoll:
kind of like a tool of working with pack work. Uh, because for the longest time I've I've wanted to have like the ability to not just require the entire You know Rails Eco system with every file right, I know, there was a while ago with somebody from Stripe that Was working on their own loader to load individual files and be able to do some static analysis To also not do that. How are you guys working with that And do you have it like? Can you use pack work in that way where it works with an auto loader or something to handle that resolution?
Alex_Evanczuk
So let's see. I think I understand what you're what you're asking. So the one way that we've used this tool chain is once you start describing the dependencies between between these packs. When you run tests, you can use the dependcygraph and use sort of first principles about dependency graphs to know how one change could affect other parts of that dependency graph. Now, when you change uh, uh, rails, your application might break, But when you change your application, Rails itself is not gonna break for everyone else just because of what depends on what.
Charles Max_Wood:
Hm,
Alex_Evanczuk
So we have this feature called conditional built where when someone pushes the c I with a change, it will only run tests for the portions of the application that depend on the thing being changed. That's kind of one way that you can build tooling on top The dependency graph. Terms of loading, we don't yet segments, or manipulate. how now Zit work will out, load or eager, load portions of the application. It's certainly a dream of ours is that we can use this ego system to uh. effectively, You know, this whole debate with micro services, vers minalith, And usually that's the first decision that someone makes Okay. I want this to be in the mode, or I want this to be in a micro service. And what
Charles Max_Wood:
Hm,
Alex_Evanczuk
we hope is that by using this sort of tool chain some day we can get to a point where once you've effectively modularized enough of the dependencies of your system, the tool chain itself can pick up on the fact that something can be deployed as a separate application and do that programmatically. that's just kind of the North Star Vision.
Charles Max_Wood:
So I guess the next question that I have is at what point does it start making sense to modularize? right. I mean, it sounds like a solution to a problem that I mean
Alex_Evanczuk
Sure,
Charles Max_Wood:
I have.
Alex_Evanczuk
definitely awesome question. and uh, uh, yeah, you know we. We don't necessarily want to modulrize just to modulorize, because you know we live in the world of constraints and you know businesses only have so much money to work on certain things. There might not be a point. So we modularize because it makes sense, you know, because it's maybe it enables new prod Options. Maybe it reduces duplicate work. you know, Maybe instead of everyone rebuilding their own, you know slack. notify R. you modularize a little Slack notifier. Maybe you're doing it because the complexity is too high and you need to be able to think about certain components in isolation. On the flip side, There's definitely a lot of times you don't need to modulerize. Perhaps the you know, every time you modularize it creates Direction between something having pay role and payments. Coupled as one, means that you don't have to make that jump of thinking about how these kind of going through these different inter faces. It's sort of one concepts. Maybe there's just other big bigger fish to fry. You know, maybe system is working. Why change? and there are other business opportunities, so it really comes down to what are the needs of the business and do the promises of modularization. Do the folks who are on the ground and have have all spoke with one another? Do they agree that it'll help solve the problem?
Charles Max_Wood:
So it sounds like you have to have a conversation about it. You have to talk to the people who re involve the stake holders and figure
Alex_Evanczuk
Definitely,
Charles Max_Wood:
it out. There's not. There's not a hard and fast rule.
Alex_Evanczuk
No, and if anyone feels like they have found a rule, I would definitely love to hear it because you know I've still been trying to answer this question and provide some sort of guidance on it, but you know I think it's a. It's a time when you can really trust the ices, You individual contributors, as we call them. Now, the folks who are
Charles Max_Wood:
Hm,
Alex_Evanczuk
making the changes to their system. they are often the ones who are the best equipped to say. Hey, this system is too hard to change. Everything is too coupled and I can't break my change that down into. you know, small small pieces, or you know keep. I keep rebuilding the same thing. we should. We should extract this this thing so you know, I don't think that kind of passing down guidance from you know, top down necessarily makes sense, but giving you know empowering people to Have that opportunity. That if they think that spending time on structural improvements is worth their time, I think it's enough to just encourage them and to give them that space and give them the mentor ship to do that work.
Valentino_Stoll:
You know, the talking about the process. One thing I always find myself doing any time I find kind of the domain boundaries starting to get blended with. You know things that shouldn't be blended right. I start breaking it out into its own like section in the code base right, with just straight up name spacing and trying to tackle the problem just from a name space perspective. So
Alex_Evanczuk
Oh
Valentino_Stoll:
I mean,
Alex_Evanczuk
yeah,
Valentino_Stoll:
if you think about like your transition with pack work like out At point in that like setting up just name space boundaries. Are you like Okay? This kind of really belongs in its own pack. Like where does that blend start? Like where you're like Okay. it's ready. like it. Really there. Deciding factors for you, where you're like definitely should be its own pack versus the name space is fine.
Alex_Evanczuk
So I would say short answer. No, as far as hard guide line, you know, I found with all this work is that there are very rarely hard and fast rules. That being said, one thing I do want to mention is one of the tools in this ego system. Rub cop packs has a ruble cop for name space enforcements, so if you turn it on for a pack, it will basically enforce that everything in that pack is You're a single. global name Space Is One of the things that we found was that in our large Rails application is we just had so much pollution in the global name space, and not only was that tough for collisions and things like that, but also trying to create a bounded context as some folks in the industry refer to it as you know. this, like surrounding around piece of the code. Um, but yeah, in terms of like When, so put something in his own pack. you know. Uh, I'm not sure. One of the things that we really like about packs is that the overhead for a pack is very low, and this is something that's all ihthink a little bit different compared to a gem. Sometimes you know, with a gem there's sometimes quite a bit of boiler plate especially for an engine. But it's nice with a pack Is overhead is so low To put something in its own pack, so you can make something that Single file, you know, with a single little helpful utility or a huge sub service can be its own pack, and I think it really comes down to if I keep thinking that one part of the pack is totally unrelated to its its neighbors within that pack, And my mental model is that there is a a really well defined relationship between separate components of the pack. Then I might. I might break that up.
Valentino_Stoll:
So I'm curious too, then, Because I'm trying to imagine you know using packs and like where we're kind of like Where all of the features really start to shine right.
Alex_Evanczuk
Sure,
Valentino_Stoll:
So like like were. What about like working within with the smaller and more modular pieces of it like Way out, Perform, or you know, the benefits are just so much better than working with like a strict name, space, or gems or engines or something like that That are just so clear right like where you're like. Oh, ye. Well, we wouldn't use anything else.
Alex_Evanczuk
Yeah, it's uh. it's a good question. and one thing I should say is that the H. the tool is a lot of the value from the tool comes in how it's used. You know it's it's. Are we drawing the right boundaries? And I think that if you were using the tool and you know the boundaries, domain boundaries aren't great, then someone might not get a lot of value Uh from the tool, but you know it's uh. We actually found value in it right from the start. You know. the very first thing we did was we. We had had ownership of code. We have this. One of the tools in this tool train is called code ownership, So we had all the code in our system owned by a team. So the first thing we did and and I wouldn't necessarily recommend it, but we moved the code into packs based on The the team who own the code, and that was sort of intentionally bad. You know you don't want to divide code based on organizational boundaries, But it started to push folks to think about. Okay, what is the domain? The domain model for the code that I own. Whereas, if you think about traditional Rails applications, all of the models are in one place, all of the you know controllers are in one place, But that means that when you're starting to work on a feature, You're jumping across these architectural layers. you know, your, your, Your deft isn't really co. located. The deft that you make is spread across the whole code base. So we noticed basically immediately was that our deft tended to be more isolated. You know, it was like Hey, I'm working within
Charles Max_Wood:
Hm,
Alex_Evanczuk
one place of the code base. But yeah, other other than that, Um, I'm not sure if that answered your question.
Valentino_Stoll:
Yeah, I think it's started to make more sense,
Charles Max_Wood:
Yeah, I mean, for me, you know what you're talking about here with this is. um. Yeah, it's easier to keep track of changes. It's easier to manage those parts. the code based on their own, test them on their own. Um, and then right, you just manage the boundary as far as how everything else connects to it. Um, And so as long as you're explicit about, you know how things talk to it and how it talks to other things than it. It becomes a lot. Or because the things you're doing now only affect this small part of the code, Um, or at least
Alex_Evanczuk
Yeah,
Charles Max_Wood:
that ideally,
Alex_Evanczuk
Yeah, like, let's one thing. One way I think about it is a really large system. We want to be able to make changes out of really large scale. You know, in order to have a lot of leverage as an organization, the problem is if you have a really, in order to make large changes, you kind of need to have some sort of pattern Et scale, some sort of structure at scale where you can back up and say Okay, this is how the system is Intended to be light out. You know this depends on that. This depends on that, and
Charles Max_Wood:
Hm,
Alex_Evanczuk
I think that's where sometimes the most value comes in. Because what we found with gems and engines is that it is really hard to use. I mean, there are great tools if you can get there, and if you start in an engine, and of course it's necessary if you want to distribute and publish your your library, but using what we call unbuilt Components, you know where you have a gem just within your application. Uh, it, it becomes hard. It's really hard to take large and tangled application and divide it into gems that have you know. An Aciclick dependency graph ends up being just
Charles Max_Wood:
Hm,
Alex_Evanczuk
incredibly challenging. technical problem. On the other hand, with packs and with pack work arriving at that that whole mental model where everything is in a pack, every Thing is in sort of a modularized folder is considerably easier and it lets you sort of bypass things that are incredible technical challenges that have relatively low value. And that's what we found sometimes with engines is that it forces you to to attempt to solve really really hard technical challenges in your system just to reach a technical ideal of it being in an engine, you know, But then it may not actually have a lot of business. You just solve that problem, So we're left with pack work. Is that we may say, Hey, this depends on this, but actually there are what pack work calls violations. To that. There are places where the system doesn't actually respect the stated boundaries. But then the beauty is, you have the freedom to choose whether not to invest in that structural change. You can say Hey, it's worth the cost to better modularized that reference you now to couple up thing, or to invert a dependency or so on, Or you can leave it beat and move on. move on to other things. It kind of gives you a lot of freedom to tackle the problem from different angles rather than the angles that extracting to a rails engine forces you in.
Valentino_Stoll:
So
Charles Max_Wood:
So
Valentino_Stoll:
I'm curious at.
Charles Max_Wood:
okay,
Valentino_Stoll:
I'm curious. What level of modularization we're talking right, because uh, let's say like one of the biggest problems with a giant Rails, monolith starts to become like the user model, right, or accounts, or something
Alex_Evanczuk
Oh,
Valentino_Stoll:
like that
Alex_Evanczuk
definitely
Valentino_Stoll:
right where it's like
Alex_Evanczuk
yes.
Valentino_Stoll:
the most requested and used like dependency in the app and all
Alex_Evanczuk
Yep.
Valentino_Stoll:
the apes related to it, Right, like how do you start sharing something like that within
Alex_Evanczuk
Oh
Valentino_Stoll:
pacts? Right, Like how does that like? It's not Really top down right at this point, because it's becoming modular. Like how
Alex_Evanczuk
Yes.
Valentino_Stoll:
do you start sharing like these key pieces, like a user model or something like this?
Alex_Evanczuk
Yeah.
Valentino_Stoll:
Across all the packs that may be are are independent by nature because they all depend on the origin code.
Alex_Evanczuk
Great. great question. and this is top of mind, Actually a gusto at the moment. So are core models. You know, some people call them God models, or Spigetti models, something like that. And yeah, so those models tends to grow very, very large and they tend to have. They tend to be the sort of de facto entry point into a lot of Ap. You know, you say so for gusto, it's company I Loy most user too, but actually company and employer the biggest ones. So it's like company, and maybe we have a method like Company dots, payroll process or something, making that up. Uh, Well, we also have company dots, you know, benefits process, and every other a P in the system, and the you know people keep adding columns to it and it becomes a central point of entanglement, where as you said, everything depends on and it depends on everything. So this, you know, You Extract that into an engine. You know, because it depends on everything would be so hard. So we did something kind of maybe, kind of silly. We pulled the company and employ models into a pack called Company Spigettimodel. That's what the pack is called, and it's probably illustrative. You know, it says he. This is piety and the dependency list is basically empty, which means that people will see What's called dependency violation if they add their domain into company. So basically we're using this system to uh. Kind of, it's kind of like a rube cop for preventing future entanglement, preventing future growth of this model. And what we've done is we started to actually work down that list, burned down that list of dependency violations in company, and so far we've removed probably like a dozen columns from our company model. You know, a bunch of associations, a ton of methods, and our goal is that a gusto a company is a really simple concept, But it's these other systems that extends the idea of a company without necessarily affecting that core model. You know. Uh, so yeah, and then in essence, what that means is that everything depends on company, but we can set that long term goal. That company itself doesn't depend on anything.
Charles Max_Wood:
Right,
Valentino_Stoll:
So
Charles Max_Wood:
well,
Valentino_Stoll:
so building on that, I just had to follow up. Like Where where do you start? Like how do you start pulling pieces of that off in meaningful chunks, right like
Alex_Evanczuk
Yeah,
Valentino_Stoll:
H. If you have, like this specific company thing that shared across a few different things, like I imagine, the naming of that is going to start to get strange to like. Do you have a process for that? Is there something pack work has that helps in figuring these things out? or is that more of like Just an analysis on your part?
Alex_Evanczuk
So pack work will tell you what company depends on with. You know various sort of copy copy outs About what that means exactly. But how do you start pulling things out? I guess like, slightly painfully, you know you, you look at a callemand, You say hey, This definitely doesn't belong on the core company model. This
Charles Max_Wood:
Hm,
Alex_Evanczuk
is. This belongs somewhere else, belongs in different domain, and from there there are couple of Strategies you can use. You know, one thing that you can use is you can say Okay, I'm going to build an a p. I to access the data from that column and migrate everything to use that a pi, rather than call company, dot my column. Then once everything is using that a pi, which sort of presents a facade of existing in a different pack, and then you can start to swap out that implementation and have a point to you. Now point to a different model. you know. Start double writing to that column and then you switch over the read and then you stop double writing. You know all while kind of trying to think about and plus ones that you may be introducing by moving the column. But actually what we started with was we just looked at methods just playing old methods even, and we move those methods off of company. So instead of company, dot my method, we may have you know my name space, Colin, Colin, Or my name Space Dots, something about company. You know what I mean, And so it still
Charles Max_Wood:
Hm,
Alex_Evanczuk
might actually ask company for that information, but we begin to move that a pi off of company, kind of allowing us to start to swap that implementation
Charles Max_Wood:
Yeah, you're inverting the dependency so that you have
Alex_Evanczuk
Exactly
Charles Max_Wood:
an inter face that you can call instead of, and this is spelled out again in clean architecture. But you invert the dependency so that your graph isn't cyclical anymore.
Alex_Evanczuk
Exactly. and I just want to call out that sometimes doing this has no business value. Sometimes due has no clear business value. But take company, for example, we have a whole team as you can imagine, that wants to focus on make bringing more people into agustom. You know they want to make it easier for people to sign up. But when you have a a large the getting model that people keep adding To Every time you add a new valid, you got a new call. You got a new validation. Trying to create that model becomes more challenging not only for end users who may have to specify more information in order to become part of the platform, but for users who are doing test set up, you know, and they need to create a company now. Oh my God, have to create the universe just to test my future, So Ye don't know he was going with that, but yeah,
Charles Max_Wood:
No, it makes sense right, because at the end of the day, M. what you're looking at, it's not just the cyclical dependencies and how many of those you have, but it's also the complexity of the a P. I surface, between between modules are between packs, And so the more you have to do, the more work you have to do. the more specification you have to meet. the harder it is, and yeah, so the simpler you can keep it, and the easier it is to keep track of this stuff, And the more that you can extract a lot of that M dependency layer out to a modul. or you know, even a mix in that gives people a way of getting the information they need without depending directly on the model. Um. it allows you to redirect a lot of that stuff and keep your code a lot simpler. And anyway it pays off like you said. not just for the code who you know. At this point I know I need these four things out of the The company modul or the company pack, but also for like you, said the user, who now has higher constraint on what they can do. And and it makes it more rigid, And you want elastic code that you can you know, flex and play with a little bit. And the heavier you put that burden, the harder it is to change, and that's ultimately painful when it comes to writing code. Because if you change it and you mess up with the specification And you have multiple things depending on it, instead of depending on that that ship layer, that module that you've created you start having more issues and it makes the rest of your code more rigid. And so that that's the game you're playing is you're restricting that a pi surface by inverting the dependency and putting that module out there, and then you're cleaning up all your code because you only have to care about those handful of things and not putting those constraints and that rigidity into the next module Or the next pack over. that has to depend on your company. And then you can like you said, You can start teasing some of these other pieces out, and hopefully eventually, Um, your dependency graph will eliminate a lot of the cycles that you have, and it will simplify the inter face to the the company pack to the point where it's just something that you deal with on a regular basis and you don't have the major issues that you're talking about.
Alex_Evanczuk
You got you know. It's something we're still working on something we're still learning
Charles Max_Wood:
Hm.
Alex_Evanczuk
a lot about. and uh, I think it's part of the evolution of a system. You know, I think that if someone sees their core models growing and growing larger and larger, that isn't necessarily something they need to fret about immediately, because you know scrappiness or trade offs about design are well, they're trade off, You know, and if moving faster by you know, not only maybe do we want to not always focused on the interface in the beginning, but we don't necesarily know the boundaries. We don't necsarily know the domains when we're first learning about them. You know when the start
Charles Max_Wood:
Hm,
Alex_Evanczuk
up or even a large Org is learning about their customers needs. They don't know. they don't have that shape in their head of what the model is that fits those needs. So we just sort of throw it together. You know we're like this works. This solves the problem. But then after a while we're like, Oh gosh, this whole thing kind of kind of feels like a rude Goldburg machine. You know, the domino hits the lighter, which burns the string and the ping pong ball. it falls.
Charles Max_Wood:
Yeah,
Alex_Evanczuk
And so then you know, starting to back up and say, let's let's put some structure on this, so that's kind of what we're on about.
Charles Max_Wood:
So I want to get into implementation a little bit, so let's say that I've
Alex_Evanczuk
Please.
Charles Max_Wood:
identified something that I want to move into a pack. How do I use pack work to do it?
Alex_Evanczuk
Yeah, so, um, but see, the first thing I want to plug if I may is that there is a community slack server for questions and help and talking about all this stuff and I'm not sure if we can put something down in the show notes or
Charles Max_Wood:
Definitely,
Alex_Evanczuk
awesome. I also have a link here, Tiny r l, dot com slash Ruby Slack. So I hope that works. By the time this goes out. Still folks want to try that And that's just you know, very welcoming community of industry professionals and people interested in Ruby and Rails modularity. So yeah, great place to ask questions. Now, back to your question implementation. So pack work itself doesn't give many tools to create a pack or tea o files into packs. It gives you A declarative specification for defining a pack, but yeah, it doesn't give the tools, so we have open source. a lot of our tool chain around this. That's kind of all in the Get hub, dot Com, slash Ruby Et scale is the Origo All this stuff is and that's linked in the block post too. So there's this gem we open source called Use packs, where, as the name suggests, all that using packs, And it exposes a c, l, I bin slash packs and has a kind of fancy interactive thing going on which I think is kind of nifty. So you tie in packs and then it gives you so after you've set up, packs should back up, you have to first set up packs Rails. And what packs rails does is that it tells rails to add packs to the auto load packs for rails, So basically, As long as you're following the structure specified in the readmit, you won't have to mess around too much with rails, con Fig. in order to get things to load the way you want. That's the first step. And then what binpack does use packs? Is it lets you create a pack. You know you give it a name. It creates a folder with a pack of Amel. There's a move function which is kind of a fancy Rails in form Utility for file, You know Dot move. Basically, it moves the file and moves its speck file. It updates references in Rubocopto, Do so you can move files without thinking about all the other stuff You have to do as a little bit of like a plug in system. If your architecture has other things that are coupled to file structure and file location, But that's kind of all there is to it. You know you create a pack, which is Just um, um, you know, Make how you pronounce that you know you create a directory,
Charles Max_Wood:
Hm.
Alex_Evanczuk
and you, you move a file into it and then pack work, being a static analysis tool, You run the pack work tool, and it will basically you do some as T Magic and Parson files to determine the relationship between the packs based on the code that's in those packs.
Charles Max_Wood:
Nice. So are the packs then, Because the way you're talking about it now it sounds like a pack isn't necessarily then. like an internal gym or something, that could just be a collection of code within your Rails app or your Ruby app. That
Alex_Evanczuk
Definitely,
Charles Max_Wood:
that doesn't get loaded. That way, it's just pulled in through load paths. Just like anything else.
Alex_Evanczuk
That's right, and that's something that I really love about it Is that this whole system is, for all intents and purposes, it doesn't and shouldn't affect your run time at all. You know. besides, of course, name space changes that you may
Charles Max_Wood:
Uh
Alex_Evanczuk
or may not
Charles Max_Wood:
huh,
Alex_Evanczuk
make. But actually, when you move a file between packs, something that we love is that you don't have to change the name space at all, which means you know all that Really is is just changing the auto loaded portion of that path, But all of the references to the constant you know, Constans classes or modules, The fine within the moved file. Those can remain the same. You know. it's the same definition because the path doesn't define doesn't become part of the name space definition. If that's not to get too much into the nittigrity of Autolo, And and all that stuff and rails. But yeah,
Charles Max_Wood:
Yeah, that's that's for another episode,
Alex_Evanczuk
For
Charles Max_Wood:
Valentino.
Alex_Evanczuk
sure,
Charles Max_Wood:
I feel like I've been hogging the mice. Do you? do you have stuff you want to jump in with?
Valentino_Stoll:
Yeah, I wanted to talk about testing because
Alex_Evanczuk
Please.
Valentino_Stoll:
the, I mean, one of the biggest hopes that I have for like static Annalys, tools like this is that you know it doesn't take an hour or half hour or whatever it may be to run tire test suit for like a one file change right like, do you start to see
Alex_Evanczuk
Sure.
Valentino_Stoll:
that using packs, or is there still the same kind of problem?
Alex_Evanczuk
Uh, okay, so yeah, a lot to unpack. No pun intended. Let's see. so First off I should mention, is that something cool with pack radls Is that the test files are co located next to the Cod they're testing, So you may have like packs, payments, App models, Pay roll are not payments. You know, models, No, Our entry, and then you packs payments, Speck models, or whatever the path may be. So that's the first thing and that's just kind of nice and a huge just for finding spect files, even though you know you may have your own kind of hot keys and stuff, but in terms of test, speed up, so you know every time you just to get to the principles for a second, every time you run a test, you need to load all of the code that you do Dot. So if your code is still entangled, even if it's in a pack, Well, you still need to load that code and that's something that rails through Zit work. The outer loader will do for you automatically it automatically, So so If your, if your code depends on the rest of your application and the application depends on everything, then you won't see any improvements. The improvement S come when you begin to disentangle things And begin to manage that dependency graph and start to isolate something, at which point in theory you know the less code will load, and actually, in practice we, we only run a subset of our tests in C. I, based on what's changed, so uh, yes, we short answer, I guess is yes, that we do see some improvements there, but it's not Immediate, you know, and you really got to do all the hard work going in there and and isolating code.
Valentino_Stoll:
So at what point do you get to the to where you can like safely have your ci run only specific tests that you know. Because you're using static analysis so heavily in packs. Right
Alex_Evanczuk
Hm.
Valentino_Stoll:
like that, you could know the graph of Okay. Well, we know this won't affect pretty much ninety per cent of the entire application, So we don't need to run tests for nine. You know ninety percent of our test space. like are you Or like, How long did it take to get there if you are there?
Alex_Evanczuk
Well, we are definitely not there yet. There's you know. there's still a lot of entangled code. And And and it's not because of anything we've done right, you know, or done wrong. Excuse me, it's because I think of things we've done right. You know, we're still alive as a business, and doing really really well because of the trade offs we made and all the hard work everyone put in but you, not now. we're facing different problems And yeah, we're We're still pretty far from it, you know, and there's a lot of work ahead of us to really isolate Um things to make our dependenciograph a sick lick, so we can really unlock the full potential of conditional builds.
Valentino_Stoll:
So I guess my follow up would be like. Is there anything that you wish you had done that could set you up for a better place now? Like? Is there
Alex_Evanczuk
Sure,
Valentino_Stoll:
anything you could do like rhetor? like, not retro, but like you know, preemptively
Alex_Evanczuk
Yeah,
Valentino_Stoll:
to help make that transition better.
Alex_Evanczuk
Sure, well, so I first want to at a disclaimer that you know hindsight is twenty twenty. And perhaps if we went back and we did all the things I'm going to say, then we would have spent too much time on technical excellence and we wouldn't have you know found product market it. So that's the. that's my disclaimer.
Charles Max_Wood:
Hm?
Alex_Evanczuk
So yeah, take everything I say with a great salt. that being said, let's see, I think that Babel would have pushed on keeping those you. now, God models Pagett models, keeping them light weight and making sure that extensions of those concepts live in isolated modules from the gecko, you know, and always kind of thinking. How easy will it be for me to completely delate this feature? You know. Is it is it entangled within the existing system or is it is it well isolated? Um, I think I would have you know. I recommend Um. going back. you know, not necessarily spending a ton of time just doing whatever, and then spending a long period of time with structural work and refractor work, but interleving those activities Now doing a little bit of okay. I'm gonna try to find that product
Charles Max_Wood:
Oh,
Alex_Evanczuk
market fit. Okay, I think I found something. I'm gonna kind of come Clean up this system and improve it. improve it. Create the A P. S. I want, fix up the dependencies that I just kind of hack together because I needed to make it work and do that clean up. You know, I think so often we consider a project done when there's still a lot of clean up. Whether that be? Oh, I have to stop double writing this column and drop
Charles Max_Wood:
Hm,
Alex_Evanczuk
the other one or you know so and so forth, but really like you know, making sure to commit to that clean up. Perhaps
Charles Max_Wood:
Makes sense. We're kind of gettin toward the end of our time and I need to for another call so
Alex_Evanczuk
Sure.
Charles Max_Wood:
I'm going to start heading us toward wrap up. But if people want to learn more about this or connect with you on the internet, where do they find you?
Alex_Evanczuk
Oh yeah, so not on too many of the social media things these days, but you can mail Alex, Eventual Gem dot com. I'm on Dot Slack server that I mentioned, and you have really encourage anyone to join you can of any experience level, beginner to expert. You know, we would love to have you. Fresh ideas are welcome. And Yeah, that's about. that's about it.
Charles Max_Wood:
All right? Good deal Now Before we do pick, we added a segment where we talk about. We're working on these days. So Valentina, what are you working on? The people should know about
Valentino_Stoll:
Uh, yeah, pretty much the same thing I am working on a H. You know a system for docimity called Doc g, P, T. That basically let's doctors take advantage of the chat cept large language model in health care context, And it's just so much fun learning. You know new ways to adapt a I into it and retrofitit into a business. It's just so much fun and so much potential there. Uh, so I've been working heavy on that,
Charles Max_Wood:
Awesome. I'm trying to find the exact listing for What I wanted to bring up, so just give me a second and I'll have this edited All right. So what I'm working on? I've kind of talked about all the things I've got going on. I've figured out I was over extending myself, so I've cut way back and I'm just going a focus on one thing and so I'm just going to run through what it What it looks like. So essentially, um, when I was talking to my business coach and he mentioned, like I said that I was doing too much and so he got me to narrow things down so effectively, I'm going to be doing video series like Rails casts or drifting Ruby. Um, and I'm getting ready to launch it. I found a platform to, so that will be my picks. That then I'm going to run it on, but yeah, I want to do things a little bit different from The way that I've seen him done with other folks in their video series. I am going to do at least two videos a week like Rails Cast did Right when I'll be free. Want to be paid? Um, but the thing I'm going to add on top of it is, I want to do a monthly call with the people who are signed up, so you know we'll just get on. I'll do a ten fifteen minute presentation on something. I'll let people help me decide what that is if you're signed up and then we'll do the call. Um, I'm also going to be doing it, so I'm doing one on Ruby or Ray, Les, or I might do to. I might do one on Ruby. stuff that's not Rails, and one that's Ruby, or in this Rails, But I'm also doing one on Java script. I'm doing one on Dev Tools, so we're thinking I'm thinking like Docker, Visual Studio code. Get that kind of stuff and then I'm doing one on Deb careers right, So I'm going a start the four of them and then, if you want to buy the overarching membership, that's going to be the full membership and full members. They're also gonna get a bonus call every month, and occasionally I'm gonna Out smaller courses and they'll just get access to those, and then when I do get back around to that other stuff like the conferences or whatever, then you'll get first crack at buying the best seats. Basically so, if you're interested in that, go to Topendeps Dot com. click on the sign up link. If you've already signed up for something in the past, you'll get an email from me telling you how to move to the new system. And if you, if you haven't, or if you have just a free account, then I'll let you know how to get Any frebies that you should have had access to, But from there yeah, we're just going a pull it ahead so keep an out for that. I've already started recording videos. Um, and so yeah, that's what I'm working on right now, Alex. what are you working on that people should know about
Alex_Evanczuk
Oh, thank you. thank you for sharing that sound pretty busy. So what am I working on? Mostly A lot of this stuff. You know what I found? I've just been kind of constantly how mold by how difficult some of this work is, and trying to figure out how to kind of put the right pieces in place, so you know we can scale our monolith, and you give people the tools. At this immediate time, We are trying to get all of our R code and our code based to be owned by a team. You know, we, as you can imagine, you know, people make changes the code and they leave, and then code is left without an owner, So we are using this open source tool code ownership to make sure that all codes owns, and then kind of start to try to give, kind of standardize on some metrics that team Can use to assess the kind of ongoing stability and operational kind of capabilities of the product. So kind of stuff like that,
Charles Max_Wood:
Awesome? All right? Well, let's do some picks. Valentino. What do you have in the way of picks?
Valentino_Stoll:
So I've been following the Ruby thirtieth event on Twitter. And it's it's all in Japanese, the live event, so I've waited and now it's now it's on Youtube and you can kind of auto translate close captions, which is nice, So I've been going back and watching that. It's kind of wild to see all of the responses from the Ruby community on there. Um, so that's my pick for for today?
Charles Max_Wood:
Awesome? I've got a whole bunch of picks I'm going to throw out, so I'm gonna go fast. The first one is, I'm goin to pick a game called The Quacks of Quidlinburg, I was pick forward game at the beginning, Quacks of Quidlinburg, Effectively, you have a potion you're trying to brew, and you draw ingredients out of a bag and you place them in your caldron, and you're trying to score the highest you can without your potion exploding and your potion explodes. If you get Many white ingredients in your potion is the way that it goes. So you know, you pull out a green one and you put it down. You pull out a red one and you put it down and you pull out a uh. you know, and then they're all numbered and you you move up the track, Um, and then you get points. You get more bonuses if you don't explode your potion than if you do. You can still win if you explode some of your potions. But it's a little bit harder. And so you're You're getting on To buy more ingredients. You get victory points anyway, it's it's great. Really, Enjoy that. you also get gems that look like rubies. which makes me happy that you can buy bonuses with. So anyway, Board game geek ranks it at one point nine, nine. So it's right in there at the casual game or level. You don't have to be a hard cord board game nut like I am, to enjoy the game and not feel overwhelmed. Some of the other games I've picked on here. It's like if you're not a hard cord game where you're just going to, you're going to read the rule book and say nope. But anyway, this one is definitely in the realm of the casual game And it's It's a lot of fun. We played it while we were down in Saint George. My wife and I got away with my father in law and my sister in law and her husband, and we just you know, walked through houses and played games. It was a ton of fun and sat in the hot tub. Um, so a few other picks? I told you I was going to talk About the platform I'm using for the courses. Now I made the mistake of thinking of course, platform, I can build that, and it turns out that I can build that, but it's going to take me a whole lot more time and not really add a ton of value. And so I want to start getting the content out, So I figured out that the C. M I've been using to reach out to sponsors and that we're moving all of our podcast cast out Reach to also has membership sweet to it. And so I Crack that open. I had to pay a little extra to turn it on, but yeah, it's so what I've been using is pipeline pro, Um. You can get a lifetime license to the kind of the basic C, r, M. and then they have marketing and automation add on, which costs like a hundred bucks a month, and then the membership add on, which is like fifty bucks a month. And so I am still paying a monthly fee for it, but unlike some of the other systems I've used, there's no limit to how much I can put into it, so I can put Many memberships in as I want, and you know as many of these other things in as I want, And then you can just sign into the portal, and you get access to all of the courses, all of the series and everything else that's involved. So if you sign in and you sign up for Like the rails clips, is what I called it. I'm trying to find another name for the Ruby one. I was going to do Ruby clips, but somebody already owns the domain and it's kind of not safe for work Kind of site. So
Alex_Evanczuk
Gotcha
Charles Max_Wood:
anyway, so I'm going to name it something else, But anyway, if so, because I kind of do want to do two series, Bill, get in and it'll show you all of the lessons that I've done, or all the twutorials. Whatever I decie to call them. It'll show you the meat ups, and then it'll show you any other resources that we put out, because I also want to put together some kind of home, work or assignment or something and give people the opportunity to come back and say Hey, I built The thing that Chuck said to build, And here's my example, and we give feedback on the code. So aanyway, So yeah, so I really like it. It's really simple to use and is pretty straight forward And then I don't have to go pay a hundred and fifty bucks a month to teach a bowl or something in order to use it. It's just you know it's there and I can use it the way I want, so over all, I've been really really happy with Pipe Line Pro just for all the stuff that I'm doing with it. If you're going to go set up assist. I like this. A friend of mine has set his up and he doesn't need all the fancy C, r M. features. He's using his system called Cartra, with a k, k, a r t, r A. So that's another one you may want to look at if you're looking to do courses and stuff like that. So anyway, those are my picks. One other pick. I watched the last episode of Nineteen twenty. three. Of course, they kind of leave you on a cliff hanger. I was hoping they. You know, they wrap the story up like that at eighteen, The three, but they didn't. But anyway, I really enjoyed that, so I'm going to pick that as well, All right, Alex. What are your picks?
Alex_Evanczuk
All right. Let's see we're like, So I don't have much in the way of software stuff, but see other sorts of media. I don't know if anyone's in gardening, but living in Vermont we. we like the garden a lot, and I listen to a lot of this podcast called the Joe Gardener Podcast. And yea, it gives you the lowdown on. You know everything you need to know around soil, Hell, And plants. you know, maintenance and care throughout the seasons. That's really important to to us and to me personally, is those sorts of ideas. and gosh, I feels great to grow and eat some of your own food. I love that feeling
Charles Max_Wood:
Hm,
Alex_Evanczuk
and I guess one. you know, I just got a notification on my phone that there's a new season of Mandalorian out. You know, I saw a Star Wars poster behind you, Charles. So
Charles Max_Wood:
Oh, yeah,
Alex_Evanczuk
Pretty excited about that because I really enjoyed the other seasons.
Charles Max_Wood:
Yeah, that one was pretty good. I didn't realize. I think I saw something about it on Twitter. but I didn't realize that they were tweeting about new season being out. So that's exciting.
Alex_Evanczuk
Yeah,
Charles Max_Wood:
All right. Well, we're gonna go ahead and wrap it up. Um, thanks for coming. This
Alex_Evanczuk
Thank
Charles Max_Wood:
was
Alex_Evanczuk
you.
Charles Max_Wood:
awesome and until next time folks max out.