Episode 5

Questions Rails Doesn't Answer

00:00:00
/
00:43:09

November 23rd, 2022

43 mins 9 secs

Your Host

About this Episode

The topic is the Rails framework. What architectural questions does Rails answer? What architectural questions does Rails not answer? Great topic, whether you're a Rubyist or not!

Transcript:

MIKE: Welcome to our podcast. I think we have a name now. I think we're going to call this The Acima Development Podcast. Nice. So welcome to The Acima Development Podcast. I'm Mike. I'll be hosting today. And let's go through and talk with some of the people who are here today. Eddy, do you want to introduce yourself?

EDDY: Like Mike said, I'm Eddy. I'm an employee here at Acima. I've been here a couple of times, and I'm in the QA department. So I'm super happy to be here.

MIKE: Great. Dave.

DAVE: Hello from the software minds. My name is Dave. I've been goofing around in Ruby for, gosh, about 15 years now, holy crap, no, 16, anyway, a long time. And I'm happy to be here.

MIKE: Ramses.

RAMSES: Hi, everyone. It's been a couple of weeks since I've been on. I'm Ramses. I've been dabbling with Ruby for a little over a year now.

MIKE: And Damon.

DAMON: Hey, everybody. I'm Damon. It's good to be here again for the ADP Podcast. I've been here for about a year and a couple of months now, sort of a freshman in Ruby, so excited to learn everything.

MIKE: Great. Today we're going to be talking about an interesting topic. This one's been interesting to me for a long time. And the topic is in the Rails framework. This applies not just to Rails. It kind of is a universal topic. Well, we'll be focusing on Rails; it's more universal.

What architectural questions does Rails not answer? What architectural questions does Rails not answer? It does answer some. That's part of why people are very quick at using it and get things up quickly because they don't have to answer so many questions that are kind of obvious. But there's a lot that it doesn't answer. This is universal across frameworks. So I think this is a really good topic, whether you're Rubyist or not.

And I wanted to start today by reading a quote from Robert C. Martin, who goes by Uncle Bob. If you're not familiar with him, change that. He's an icon in the community and talks about architecture on his Clean Code Blog. There's a post from...it looks like September 30th of 2011. And I want to read a couple of paragraphs (Looks like four paragraphs.) right from the beginning of this blog post.

He says, "Imagine that you are looking at the blueprints of a building. This document, prepared by an architect, tells you the plans for the building. What do these plans tell you?

If the plans you are looking at are for a single-family residence, then you’ll probably see a front entrance, a foyer leading to the living room, and perhaps a dining room. There’ll likely be a kitchen a short distance away, close to the dining room. Perhaps a dinette area next to the kitchen, and probably a family room close to that. As you looked at those plans, there’d be no question that you were looking at a house. The architecture would scream house.

Or, if you were looking at the architecture of a library, you’d likely see a grand entrance, an area for check-in-out clerks, reading areas, small conference rooms, and gallery after gallery capable of holding bookshelves for all the books in the library. That architecture would scream library.

So what does the architecture of your application scream? When you look at the top-level directory structure and the source files in the highest-level package, do they scream: Health Care System, or Accounting System, or Inventory Management System? Or do they scream: Rails, or Spring/Hibernate, or ASP?"

DAVE: That's a very dangerous question because, to my mind, Rails isn't an architecture; it's a style. It's kind of like going to the Parthenon. And I'm going to get my Greek architecture wrong here. But it's basically looking at this and saying, "Ah, the architecture here is Dorian, or it's Ionian because of the columns with the flutes and the substances and the scallops." To my mind, Rails should be that, when you look at a project, you should go, oh, this is a library that's built in Rails, or oh, this is a house that's built in Rails. But you're absolutely right. Too often, we look at a house, or we look at the architecture and go, yes, this is bricks.

MIKE: [laughs] Yeah, well said. These are bricks. That's absolutely what this is. And if you're a new developer coming into that project or an experienced developer in that project and you want to think about what's there, looking at a big pile of bricks is probably not very helpful to you.

DAMON: Definitely not.

MIKE: I think that's a great introduction to this discussion because we're talking about...and he mentioned three frameworks there deliberately. We're mostly going to be talking about Rails because we're a Rails shop, but this is universal. And frameworks tend to converge. There's converge and evolution where they tend to look like each other after a while. They tend to answer similar architectural questions, and then there are other questions they don't answer.

And the questions they do tend to answer are, in some ways, the easier ones. We'll say, "Oh yeah, we want to have a tiered structure, a layer that talks to the database, a layer that has our business logic, and then a layer that presents things." And we'll call that a model layer, a controller layer, and a view layer, model talking to the data, controller is dealing with your business logic, and then a view layer that's going to present things.

Rails calls itself MVC, and it sort of is, but it blurs those boundaries a little bit, I would argue. I would say that in Rails, what they call the controller and view are really both mostly a presentation layer. And the business logic layer, that actual controller layer, is largely not specified. And I think that that is the big unanswered question that we usually have to answer when we're building a Rails app.

I'm kind of drawing a line there in the sand. [laughs] This is where I'm going to make a proposal that that's where the boundaries of the framework are. They're a little bit misleading, and they have become kind of the starting point. In a big app, most of your code is probably not going to be in those three buckets; it's going to be in the actual business logic layer, which makes up most of your app. Are those consistent?

So, Dave, you've had deep experience with software development, and then all of us have had some experience. I'm particularly interested in what you have to say, Dave, if you've got thoughts about my suggestion there.

DAVE: I kind of like it. Actually, I think you said something casually revolutionary, which is that most of a large business application doesn't fit into those three boxes; I really, really like that. Rails will give you tiny architectural, I mean, there's a bunch of big architectures, but it'll give you some tiny, you know, like ionic columns are the ones that...sorry for the stupid Greek architecture reference. But the little flutes on the columns are not part of Doric architecture; those are part of Ionian architecture, which meant they came from a different group of people.

Rails will give you a thing, and it's not new to Rails, but they took on this coat and wore it boldly. They'll give you a thing that if you want to talk to an object that came from the database, you go find the class that maps to that table. And you ask the class to find you instances of rows in that table, and you get those rows back. And then, if you want to manipulate a row in the table, you talk to the objects of that class, the instances of that class.

And it's so easy to soak in Rails so deeply that you just think everything works that way, but a lot of projects don't. A lot of projects say, yeah, the objects in this system, the back office stuff, the database, housekeeping is secondary, tertiary. It's like, the most important thing we can do with this is have this object communicate to other objects and produce a viable business result. The database is just a parking lot where we put them and get them.

Rails brings this front end to the fore with that ActiveRecord architecture. And if you try to make all of your models fit into the model directory or even into the model bucket, you're going to have this problem where (And I've actually had this happen.) your application will end up looking like a database. You can actually make a map of your business model by just dumping the database tables, the ERD, the entity relationship diagram, the ERD.

I've had gigs where I literally walked in and all I did was dump the database structure and print it out on paper in a four-point font and made a poster that was like five feet wide and four feet tall. And people come in and go, "Holy crap, what is that?" And I say, "That's what you've built. And the entire point of this poster was to make you go holy crap." So, you know, this poster has served...I'm getting off on a tangent, as I am one to do.

But the point being is that if you take the architecture blindly without thinking about it, you will start laying down these defaults, put the objects in the model directory, that means they map to the database table, that means you find them by searching from the class. And that means you interact with them by interacting with the instances. Those initial default steps are in a particular direction. It just feels like you're just taking a step, but you are taking a step in a specific direction. And if you look far enough ahead, you can see the corner that you're going to wind up painted into.

MIKE: And I would argue that we do, we get into that corner. We have a hard time conceiving that there might be resources that don't map to a database table. For example, let's say you have a subscription, and you're going to cancel that subscription. And in your database, cancellation is just a single date. So you think, oh, I'm canceling my subscription. Well, that's something that I do on my subscription. And as soon as you've thought that, you've taken a step too far because you're not thinking about resources anymore. You're thinking about your database table.

DAVE: Right, because it's the user who cancels their subscription.

MIKE: The user cancels a subscription. Those are three things: there's a user thing, there's a cancellation thing, and there's a subscription thing. So presumably, you have a subscription object, but you might not have a...well, we call them objects. Why not treat that cancellation as a thing, even if it's not a first-class thing? If it doesn't have its own table in the database, so? That doesn't mean that it's not a resource that somebody is interacting with.

You're interacting with that cancellation thing. And if you structure your code around this cancellation thing, now you've followed best practices for a RESTful, you know, the REST being the representational state transfer. That's the attempt to use HTTP the way it was designed, hypertext transport protocol the way it was designed, which is to think about resources that you interact with.

Well, if you think about well, I've got this cancellation resource, and I'm just going to create a cancellation. In Rails, you create a cancellations controller with a create method. It maps directly to that REST idea, and everything just works perfectly. The only thing that's going to veer a little bit from the way you normally think about it is instead of creating a cancellation in the database, well, you probably should have one. A lot of times, there's a sign there that maybe there's an object missing, but you just write that date to your subscriptions table and done. You didn't have to have an ActiveRecord cancellation object in order to have that resource.

DAVE: So there are some people listening to this right now who are going, "But...but...but...you can do this in Rails. It doesn't prevent you." Yeah, it doesn't. It doesn't. But there are things that are uphill, and then there are things that are very steeply downhill that it's just easy to fall into them. I remember 15 years ago when web sessions were stored in a column on the user record, like, you had your session ID. And there might be a sessions table, or there might just be a cookie ID that you store on a user record, and we can look at that user. And it's a terrible security practice, don't do it that way.

I remember when the world shifted to RESTful sessions. So when you go to log in, it actually takes you to the session's controller new action. I'm like, no, I don't want to make a new session. I want to log in; logging in is what I'm doing. I don't want to create a new session. And I remember when sessions went to RESTful, and it makes sense in my brain now for sessions to be RESTful. When you log in, you create a session; when you log out, you delete your session. And oftentimes, now those are in a separate sessions table.

But when we first got into these, the thing that we got led very strongly to by the hand almost was login is going to be a thing that a user can do, and it will change the nature of that user record. That user record in the database goes from just being a user in the system to a user who is currently logged in, and we can find them, or they can be found by a cookie identifier in a browser. And that was a huge leap. Like, somebody had to come in and think really hard about what Rails wasn't doing for us with this user column and then step back and say, "Oh, we need RESTful sessions."

And I think what you've just described, Mike, this cancellations idea it's the same thing. Like if you just look at the things that are in front of you, you might be tempted to say add column to the subscriptions table, canceled at is a date time, and we're done. We just add a timestamp for when that subscription was canceled. Then there's this whole separate idea of, like, well, let's create a cancellation. Let's edit a cancellation, let's delete a cancellation, let's search for cancellations.

And to the people that are saying Rails doesn't stop you from doing that, I want to say I agree with you 100%. But Rails doesn't tell you to go that way. Rails doesn't give you any hint that that direction even exists. You have to know it's on the other side of that wall; let's punch straight through and grab it. Does that make sense? Like, that idea is kind of hidden because of the way Rails is very much built around verbs and controller actions and transactions.

And you can build RESTful things out of Rails. Rails makes it very easy to do resources add and that sort of thing. But out of the box, its route get canceled on the subscription. Cancel becomes the verb, and that's not REST which, I mean, might be okay, but it's a decision.

MIKE: You look at the documentation, and Rails will actually encourage you to build a resource. But until you made that mental leap, it's very easy to fall into that, oh, I'm just going to pack more stuff into this thing. Ramses, I believe you've recently been disentangling one of these with a significant refactoring project.

RAMSES: Yeah, it's complete now. But it was four or five weeks' worth of refactoring custom REST methods into more resourceful actions.

MIKE: What was it like when you had that realization? Like, wait, these are all just things.

RAMSES: Yeah, it's really eye-opening. It's easy to get into the mindset of oh, I can just add a custom REST method into this controller, but it doesn't quite make sense. I think it makes a lot of sense when you get out of the mindset of thinking about the object that you're interacting with has to be in the database, or it has to be a model or something. When you realize it doesn't, it makes it a lot easier to work with, I think.

MIKE: Once the code had been refactored and you saw it as a bunch of resources rather than a bunch of stuff crammed into one file, how did the code feel to you? What's your vibe? [laughs] How does it feel to you now?

RAMSES: It's a lot less cluttered rather than everything cram packed into two controllers. I think there are like eight total controllers now, but it's namespaced really greatly, I think, and abstracted out into separate concepts. So it's really easy to digest what's going on.

MIKE: I love a couple of things you said there. You said easy. [chuckles] Easy is a good thing. If you go into a project and it's hard, that's a sign that something's wrong because it means that somebody has to think about it. It means they'll likely think about a problem. It means we haven't structured it in a way that's easy for people to understand.

You also said another word for what it was like before, which is cluttered, which is another word suggesting complexity. When you see a bunch of stuff that's disorganized, chaos, or entropy, disorder, it's hard to wrap your mind around it because there's not a pattern. And if you can get away from that and put things into a consistent pattern, they're easier to think about.

And we've solved a major problem which is allowing ourselves to think about the problem, which is maybe, arguably, that's the most important thing that we solve in code is breaking up the problem into pieces that we can think about so that we can then have them do stuff. That resourceful idea is there. Rails provides it for you. But you got to take advantage of it. So that's an excellent example of something that you might not get without thinking about it.

And this applies not just to a web controller, and we're referring to controllers here in the Rails sense. But like I was saying before, it's a little bit of a stretch on that controller idea, and there's not much business logic there. But it's handling the requests that are coming in from the web and delegating that to where they need to go. Organizing those into resources, I think is hugely useful. But that applies (Dave was talking about a fractal before.) that applies I think throughout the architecture that you want to have this idea of resources so that you can think about a thing.

Like, I'm going to go interact with my subscriptions, for example. That's a resource. And within those subscriptions, I want to interact with cancellations. So there's a sub thing. It's related things. Maybe you think of it as sort of a tree, and you go through the subscriptions and get over to these cancellations, and cancellations are a thing. Once I've done that, I can think about that cancellation resource. And I might create one. I might delete one, undo the cancellation, or I might update one, and so on. Thinking about things in terms of things that are resources allows you to organize your mind into those patterns and make order out of chaos.

I've got a pivot here into another huge question that Rails doesn't answer. But I want to make sure everybody here has a chance to speak. Any other thoughts on this particular topic? We've talked a lot about this, organizing, and resources.

DAVE: This notion of creating order out of chaos, I can't express how revolutionary that idea that you gave of if you just put things in these three bins, you're going to be in trouble. There are certain things, like, Rails, makes it very, very easy to map your application domain, the high-level thing that users interact with all the way to a database. I mean, you can create one route, which creates...scaffolding up the models for it. You can fill in the forms, and you can save database records.

And if your end users are prepared to think in terms of selecting from sets of things from the database, you're going to be able to write an entire Rails app in 15 minutes, and it's the ancient build a blog in 15 minutes concept. If the idea that you have for your application does not fit well into a database, Rails won't stop you from doing it, but it also doesn't pave the way and gild the curbs, and puts nice, safe street lighting in that direction.

A good example of something that's kind of in both camps...it's like it's painful to get there but also kind of...I don't know. A good example of this is nested sets. They are really, really awkward to build in a database. There's a really clever algorithm for storing just Google nested set lgt rgt, that notion...or lft, rgt, sorry. These are database columns that you store for left and right, and they're the bounds of a subset inside a set. I realize I'm speaking gibberish.

My point is that this is a data structure. It lets you build a graph. It's like, Mike runs a team, and on that team, there are these people. And each of these people have people that they can contact that are their friends. So let's find the friends. I've got somebody who's a friend who's on this team who's under a manager, and that manager has another person; let's find their friends. That up to down to relationship is something you can do really well if you have this notion of nested sets in your database.

But reducing a nested set from object-oriented space to a database graph is very awkward, very painful, and very difficult, and when you translate that to Rails space, all of that awkward transformation in the database remains. It's really hard to make that go away. And you really hit on this, that if you try to make a database model out of this, you're going to suffer.

But if you can find a way to express it in a primary way, it's like, what is the native way to express these collections? Well, I want to do some things. I want to add a person. I want to find people based on this. Can we do this without mapping it all the way into the database? If we can, we're going to have an easy time of it. And Rails doesn't make that easy. It doesn't prevent you from doing it, but it doesn't make it easy.

And there's part of me that says, so what's my point? But that is my point is that when you make a bunch of things very, very easy, you make the things that you don't make easy, the things that you leave undescribed, but they're still possible, by default, and by comparison, those end up looking really hard. It's not something Rails is bad at; it's just something Rails doesn't do for you.

MIKE: Nor could it, and that's not Rails-specific either. As I was saying before, there's no framework that's going to answer all of your questions that's going to build your app for you. If you did, then you probably would use a no-code solution. And those exist, and they have actual value in the places that people use them. But if you're building something novel, the whole reason that you're building software is to solve a problem that wasn't solvable in another way. And the framework is probably not going to give you everything you need, and that's not a diss on the framework.

DAVE: Yeah. The architectural blueprint is meant to convey a certain idea about the thing that you are building, and you're supposed to have a look at it and see the salient points. It's not going to tell you where the library should be built. It's not going to tell you what language the book should be in. It's not going to tell you should this library be a public or a private resource. It's not going to give you any of that. It's just going to give you this is what the building is going to look like. And you can put it anywhere, and you can build it how you want. And that's good.

Ooh, now that's a dangerous question. What questions should architecture leave unanswered? It's a subtle difference from what we're doing today. What we're doing today is what architectural things does Rails leave unanswered, which is a kind of a 90-degree question.

MIKE: Well, I'm going to propose that there's another one that Rails doesn't answer that basically every Rails app is going to need to...every Rails developer is going to have to deal with. And it goes back to something I hinted at before, which is that in Rails, when they say model-view-controller, the models and controllers together, they call them Action Pack. It's really they interact with the web part. What happens if you start having background services? Those don't interact with the web. Now we don't have three buckets anymore. What do I do? [laughs]

And what if you have some logic? In our theoretical example here, we've got subscriptions with cancellations. What if when that cancellation happens, you need to do a few things? Maybe you need to contact the printer, and you need to...this is all theoretical. This is probably not how the print industry works. Maybe you need to contact the printer to tell them not to print as many. Maybe you need to send an email to the user who had a subscription to let them know that things were canceled. Maybe you also need to notify the marketing team and so on. There could be a whole series of things that need to happen.

And maybe you need to tear down some things. For example, you might need to remove access of that user to the web version. There are a lot of things that might happen there. And there's a lot of logic there. And if you put it in your web controller that handles that incoming web request, well, now it's not reusable. If you want to put it in a background job, well, you can't without tearing it out of there and putting it someplace else. Well, that's a problem. But if I put it in the background job, well, now it's only in the background job. And now I can't use it on the web. Well, that's not so good. What can I do?

DAVE: It's almost like the web code, and the background job code are means of accessing the business logic, which should be somewhere else.

MIKE: That's called --

DAVE: Sorry, I didn't mean to run straight ahead in the direction you were pointing so hard, but that's what just happened. [laughs]

MIKE: As Dave put it brilliantly, you're going to have to have a place to put your business logic and that, I think, is a key item. It's what I took from Robert Martin; again, he goes by Uncle Bob. I'm not trying to diminish him. Sometimes uncle is used as a disparaging term to diminish somebody; he calls himself that. [chuckles] But then he says here that maybe your logic ought to be structured, and that ought to be what your application looks like. What does it do?

In all of the Rails applications, I think I've seen that have scaled in a sane way, they've built...they've figured this out. They've figured out a place to put the business logic. And there's not just one way to do it. There's more than one way to solve this problem. So I'm not going to say that there's a single way. Although I do think that the industry has kind of gone one way versus another.

One way that has been done by the folks who kind of originated Rails, the Basecamp folks, is they used a lot of concerns which are...if you're not a Rubyist, you can think about it as multiple inheritance. They also call it mixins. It's not quite an interface like you'd see in Java. It's executable code that you can add. They structure those around your database models.

But then it goes down to the problem that Dave is describing. If your application doesn't really center around database tables, then that doesn't fix your problem, but it is a solution. It is a totally solid solution if you have a very database table-centric application, which is not disparaging of that application either. You can think about what you're doing has a lot of related ideas. Everything you have might want to have comments on it, for example. Then you make every one of your database access classes have the ability to add comments. And you structure it that way where it's oriented around those.

But in a lot of our applications, it isn't like that. Maybe there are a lot of third-party integrations that really don't have anything to do with your database tables, and in that case, it really needs to be somewhere else. So what if you build a whole system? And so you look, and you say Rails, okay, that's your foyer. That's your entryway. It's your spinning doors. And maybe it's fancy. Maybe it's a really cool entryway with really nice doors. But that's not your building. Your building is what comes beyond that entryway. And that is all of your business logic structure.

That is a set of reusable classes that can be called from your background jobs, or from your web servers, or from your API that you may have built separately, or from thing X that I'm not thinking of at the moment, can all call into these service objects that provide you a service which is performing that business logic that you can call from any of those places.

So now your Rails controller calls into those service objects. Your background job calls into those same service objects. And those service objects are put into a beautiful structure that hopefully, you've thought about beforehand, which, of course, none of us do [laughter], and split up into nice, neat business domain, so it's easily understood. So I'm making another proposal here; thoughts?

Damon, Eddy, Ramses, you've seen our code. And as you came into that, you probably maybe having some familiarity with Rails before saw, wow, I've got all of this code that's not in my models, views, or controllers. What is this? Did you have that moment where you saw that, like, wait, what's all this?

EDDY: For me, it was understanding that not everything fits into the app directory neatly, and there are times where you store some of that in the lib directory. And I'm like, wait, that doesn't go through convention. What is this? And then understanding that it was more in-depth than just the traditional or convention of MVC was eye-awakening for me.

MIKE: Yeah. Like, oh, I might have a library of things that are shared, that are part of this standard structure. There are different ways to structure that lib thing. People have different opinions on that, and they can have those opinions. [laughs] But your key idea is fantastic. Ramses or Damon, do you have any thoughts on this?

DAMON: I don't really have any thoughts on it per se. I just think coming into it for the first time, learning it, and looking at it, it can be super overwhelming. But when you start to actually understand this does this, this does that; it makes a lot more sense on where things go and why they should go in the place that they do.

MIKE: Thank you. And hopefully, the people who have gone before you built something...to go back to that blueprint idea if they're building a house, they made it look like a house; it's not a converted church.

DAMON: [laughs]

MIKE: I knew a guy who bought an old church and lived there for a while, [laughs] and it made kind of a weird house. It didn't fit very well. Hopefully, we've built it in such a way that you can look at that and say, oh yeah, this is what this does. I get it.

DAMON: Oh yeah, for sure.

EDDY: Until you run into legacy code.

MIKE: Yeah, and that's a huge point here is that no codebase is perfect. It's built by humans who are figuring things out as we go. And sometimes, we're going to pivot and make different changes, and the code doesn't instantaneously evolve as we do. So we're talking about what things could, in this perfect vision, look like, which means you got to take some time to get it there. [laughs]

And maybe you're going to find some things that are awkward. Going back to the refactoring that Ramses did, he found some code that wasn't very resourceful, and he fixed that. But that's the thing, he took some time, and he fixed that. And now it does follow these patterns that we can wrap our minds around. And there's always got to be part of that. We should do a whole podcast on that or two about the importance of refactoring and how you make that work when you also got to deliver things.

I think it works really well to take some fixed portion of your time that is just budgeted. You've got to budget for that and keep that as part of your budget. They call it tech debt for reasons because that financial metaphor works really well. If you don't pay it down, then you're going to pay more in the long term. You got to pay with debt. And if you always have part of that budgeted to take care of those problems, then it doesn't get out of hand.

EDDY: I personally love dabbling into tech debt from Atlas. It works both ways, right? The company or the group, rather, or the team gives the option or the opportunity for someone else who wants to take up the mantle. And it's a win-win. So truly grateful for that.

MIKE: Listen to Eddy's plug here. If you're out there listening, have some people who are not on your development team help with some of your tech debt. There are going to be some hairy problems that you probably won't hand to them, but there are going to be some things that they can do. And it's great because it's not urgent, but it's really important. There's really important work that people can work on that doesn't have to be delivered tomorrow. And it's a great opportunity for people to get familiar with the system and grow their skills without having to be under a strict timeframe, strict deadline.

Dave, we've gone around to others. What are your thoughts about this idea of a structure of service objects that ends up becoming the main part of your application? And that's the building rather than just the entryway.

DAVE: I think it's another architecture, and I think it leaves certain questions unanswered. [laughter] For me, the big notion that a centralized service that other things can talk to, the thing I like about it is that it says the presentation layer is kind of immaterial to me, the way you are accessing this business logic entity processing thing. Processing is a strong word and takes us in a certain direction. That's a poor choice.

The thing that's going to create cash flow for the business, this bit of software, being able to detangle it from the database layer, being able to detangle it from the web presentation and consumption layer, being able to...detangle is the wrong word, detach, decouple. Decouple, there we go; that's the fun word that we like. Being able to decouple it from the service processing queues coming in from the various asynchronous communication. So we've got, for our service-oriented architecture, we've got a distributed network of servers.

A lot of businesses are going to this distributed network because you just can't deal with a quarter million customers on a single server, so you need to distribute it in some way. I think it's a good solution, and I'm not sure I understand yet everywhere that...like a decoupled service from Rails, I'm not sure what questions that architecture leaves unanswered. But my instincts tell me that there are some and that there are probably some parts of that that are painful corners to get into.

You mentioned this notion of sharing these objects between systems. To just kind of throw Conway's law into the mix, if you're sharing that object with another team, so you have a whole different reporting structure, then those objects are going to be fairly defensive. And one way you might want to do this...so to be clear, what I'm talking about is like a database table or some objects or some document that you have to shuffle around the company.

And you got two separate teams writing software to interact with that document, which means you have two bits of interface code. And if one changes, the other one must change, or the change must be compatible. And you certainly can't...well, you might be able to in an emergency, but in general, you can't coordinate a simultaneous deploy to update the versions.

So that's an architectural decision that you've now kind of taken on. You now, when you change this object, you have to do it in a way that's compatible to the other team until they get around to adapting to it. You can...in Ruby; the obvious solution is, let's put this in a gem. And I think we have this in one of our projects, a couple of our projects. We have these shared models internal, in-house. And the immediate headaches that this buys us if you want to change a model, you have to publish a gem now. And that's a lot more of a pain than just migrating a database table.

But Conway's law demands it. Conway's wall, yeah, Conway's wall is the right word. So yeah, there's this extra headache that you pick up by doing that. But it does solve a problem. It makes it so that two teams can now interact with this document and make the business go forward the way we want. I'm speaking in very, very abstract terms; I apologize.

The upshot is, like, yeah, if you separate all this logic off into a service center that is agnostic to the web or to an asynchronous queuing process background job kind of thing, that's just another architectural decision. You've now got a plan that says library instead of civic center or art museum, which can be very similar architectures. But they're going to service specific needs in different ways. The art museum isn't going to have hyper-reinforced subfloors the way the library is going to because books turn out to be surprisingly heavy. They will bend your building if you don't account for that. That's a weird, random example, but yeah.

MIKE: You mentioned this idea of bigger, you know, maybe you need more than one application. Your service can actually be extracted. That's a beautiful thing that happens when you decouple. Like, well, maybe they don't even have to live in the same application, but early on, they probably do. Your services likely live in the same place. But I think you touched on a really important question that doesn't get answered.

So do I have a few hundred service objects of some kind that my business logic kind of call out, all without any hierarchy, just in one big directory? And you probably say, well, no, there's no organization there. Now I'm making things even worse, well, maybe not worse, but certainly not good. We have to figure out how to organize that stuff.

DAVE: There's a great thing that this architecture leaves. This notion of moving things into a centralized service area, a question that that leaves unanswered is how much of the business problem that our application is solving should not be solved by our team? How much of this should go off to a risk management team? Or how much of this should go off to the accounting team or to a finance team? Or how much of this should go off to...you got to think of the man who manages personnel.

Maybe part of this should actually be managed by a couple of engineers working in the human resources department, and it shouldn't be in our repo, and the data shouldn't be visible to the engineers. These are questions that are completely unanswered, but it's not until you throw it into a problem domain that you realize that, oh, this is unanswered, which is great. It doesn't mean you're forced into one way or another. It just means that the proposed solution doesn't have an answer ready.

MIKE: I think you brought up something profound there, actually. You said all these parts...you put it there, and now you have all these unanswered questions. Well, now you have questions you couldn't ask before.

DAVE: Yes. Ooh, I love that. You've actually upgraded from unasked questions to unanswered questions. I like that. I really, really like that. That's great, thank you.

MIKE: And being able to have those questions is...I would argue that questions are often more important than answers. If somebody has given you all the answers, that is a bad life. I want a life full of interesting questions, [laughter], and the ability to be able to ask those questions and have those questions and have different questions than somebody else has. Being given the opportunity to have questions is a great gift. I'm thinking of Hitchhiker's Guide to the Galaxy. They built a tremendous machine to find the answer to life, the universe, and everything. And the answer they got was totally useless. What was more important was the right question.

DAVE: What was the question? Mm-hmm.

MIKE: That, I think, is what you imply without saying it directly. You did say, "Well, now you can ask all these questions." Yeah, now you can ask all these questions. Once you have decoupled your business logic from your presentation, now you have a bunch of questions as to how you're going to organize this and where should it go, which means that you can answer those questions. You can start asking them and think, well, how do I do this? And that is powerful. Suddenly, you've been given this great gift that you didn't have before because you couldn't, and so your hands were tied.

DAVE: Yeah. I like that. There's a phrase that I got from working as a contractor for years and years, which is, you want to deliver something really, really early because the customer doesn't know what they want until you don't give it to them.

MIKE: [laughs]

DAVE: And that's that same notion of, like, there are all these questions you don't even know to ask until you actually produce something that lets somebody go, "Oh, that's, yeah, no, that's not what I wanted." And the importance is this notion going from an unknown and unasked question to knowing what the questions are is a huge upgrade, is a huge step in the right direction. That was my whole point. That's why I was going wow, a few minutes ago. I was realizing that it seems like a problem, but you've actually been handed a ton of solutions in portentous that you can then track down.

MIKE: Great. So we've talked at some length about typical questions that Rails architecture doesn't answer for you. It doesn't force you to divide your code into resources and divide your things into resources that you think about that way. It encourages it. They'll tell you to do that, but you have to solve that problem yourself. And secondly, it doesn't tell you where your business logic got to go or how you ought to organize that.

Those are some pretty big questions that go unanswered, and this is largely platform agnostic. You're going to have to answer these questions no matter what framework you're in. It's worth thinking about. And if you're not in a position where you can ask those questions, it's probably time to take a look and think, well, what are my problems here? How can I decouple things so that I can maybe start asking some different questions and doing things differently? Maybe in ways that I can't conceive of yet because I can't even see that there might be a question there.

DAVE: This was a lot of fun. Normally, when we get into what does Rails not do, it's usually a chance to get why I hate Rails off my chest. [laughs] And I wanted to go into this one with, no, I don't want to hate on Rails. I want to say what is Rails good at? What is Rails blind to? And this was definitely that. Rails gives you some architectural things. It gives you a solution to the problem of how are we going to make money on the web using a database? It will tie all of that together for you.

It's not until much later that you can turn around and go, wait a minute, what are the parts that hurt on every Rails project because of the same blind spot getting papered over? That's not a moral failing of Rails; that's just a natural consequence of some of the...it goes back to what I said earlier, the default direction you take two or three steps into will determine which corner of the room you're going to paint yourself into. There are going to be consequences of those early decisions that you make and especially if you keep heading in that direction with every default decision, kind of neat.

MIKE: Any other final words from others on the call?

DAMON: Only that you guys explained this really well, and it's super helpful. So I appreciate it.

MIKE: Fantastic. I'm glad we accomplished something. [laughs] Thank you, Damon. Thank you for joining us this morning. I think we had a great discussion. And hopefully, you've got some nice ideas to chew on and think about how you can better architect your application. See you next time.