My big beef with refactoring
This is an episode of Thoughts on Functional Programming, a podcast by Eric Normand.
I love refactoring. It's therapeutic. It helps productivity. But refactoring is not enough to write good software. We can't just write it so it works then clean it up. In this episode, I explain why.
Eric Normand: Is refactoring enough? Can we simply write our software so that it works and then clean it up, later?
My name is Eric Normand. These are my thoughts on Functional Programming.
Well, the short answer is no. We can't do that. Actually, I gave a talk about this a couple of years ago. Here is my attempt at explaining why refactoring, though it is an important idea, is not enough. We can't just rely on being able to clean stuff up later.
For thousands of years, Aristotle and his physics, was deemed the best explanation of physics that we had. Many philosophers spent their careers trying to reconcile all the problems with it.
It's just taken as gospel, I guess you could say, as given that Aristotle was right and then there are all these exceptions that didn't really fit in what he was saying.
What did Aristotle say? Aristotelian physics is a mishmash of different explanations for how things work and what's the natural order of things. One of the things that Aristotle put in his physics was an idea of Ideal Place.
Ideal Place basically says that light things float up and heavy things go down. This is why you find rocks sinking to the bottom of the ocean. There's water on top of the rocks and the dirt and then there's air on top of the water. Air, its ideal place is on top of water.
You can see that this explains quite a lot if you just pick on as why rocks roll downhill. Everything has an ideal place. You can see it does explain quite a bit if you just want a basic explanation that would satisfy someone who's not too curious.
You could just make a list, you could just rank order all things from heaviest to lightest and you would have a decent explanation of where you would expect to find stuff. The reason stuff moves, like rocks roll downhill, is because they're seeking out their ideal place.
Some things like animals can move of their own accord. When they move of their own accord, it's smooth and natural motion. That's what's called natural motion. It's motion that comes out of the thing itself.
Sometimes you get knocked around, you get hit by a cart or a bull strikes you, your limbs are flying, you've tripped, you fall over and you flipped over. That is called unnatural motion, when you get jostled by something.
There is ideal speed. Ideal speed is the notion that heavy things move slower than light things. You can take a small rock and throw it very far and very fast, you try to throw a heavy rock and it does not go as fast.
You can see it's kind of a mishmash. There's no relationship between any of the concepts, except maybe heaviness, how heavy something is, the weight of something; but it's really not a unifying theory.
Along comes Newton. I'm going to totally simplify this story. I'm not trying to do justice and I'm not going to be able to do justice to all the people who came between Aristotle and Newton. I'm just going to use them as tokens of this human accomplishment that we have as a civilization.
Newton came along and created a different system of physics and that system has three laws, Newton's laws of motion as what we tend to call them. They relate a few key concepts. Those concepts are mass, distance, time and force.
With those concepts and the relationships between them, you have F=ma, that's the relationship between force, mass and acceleration. Acceleration is a relationship between velocity and time. Velocity is a relationship between distance and time. You see how everything is related to these very basic concepts in there. That's F=ma.
You have equal and opposite reactions. It states that forces come in pairs. It talks about the direction of the forces, that their magnitudes are equal but their directions are opposite.
The third one that unless an object is acted on by a force, it's not going to change its course. If the sum of the forces equals zero, then the velocity is unchanged. ∆v is 0.
With those laws, you have a different system of physics, but it has much more explanatory power and much more predictive power. Aristotle could explain a little bit, but it's very hard to predict stuff. There is a lot of corner cases, we'll say.
You can see how Aristotelian physics came to be. It's like people had all these questions and Aristotle answered them. He was a teacher so people asked him, "Why do rocks sink to the bottom of the ocean?" He just comes with a name for that, "Oh, that's ideal place."
"Why is it hard to throw a heavy rock, but it's easy to throw a light rock?" "Oh, well that's, that's called ideal speed."
You can see that he's aggregated all these little explanations for things and it feels good. You can say, "Yes. Oh, I, I see. There's ideal speed, so I have to do is kind of learn about what all the ideal speeds of things are." That's like a wisdom you can develop over time as you go through life.
You can say, "Oh, wow, wood. Wood it has a different ideal place than rocks. OK, that I...that means something," but what you're actually doing is just aggregating all these little use cases, all these user stories.
What happens if I drop a rock in the ocean? What happens if I blow air under the water? It tries to rise up. What happens if I throw a big rock? What happens if I kick a little rock?
There's all these user stories that then have a little bit of explanation. You could even call it code. I'm trying to make a metaphor here where in modern agile software development, we tend to list requirements as user stories and then we write some code to satisfy that user story.
We never look at the whole. We just solve each one individually and we somehow still make software. What we're doing is what Aristotle did.
Like I said before, people spent thousands of years dealing with all the corner cases. The corner cases of like, "Why would a big piece of wood which is heavy, doesn't sink?" It's heavy like a rock, but it doesn't sink, because it's not about weight. We know that now, but for a long time, that was a very difficult problem.
There's all sorts of issues with all the different concepts and how they work for the average case, but then on the edges, there's all these issues where they don't work. That was the main job of the physicists back then. It was to try to reason your way through why things still make sense even when they're clearly not working right.
On the other hand, Newton's physics, his law of motion, is very elegant. It's a handful of concepts. All of them are measurable, other concepts are defined in terms of them. It's like an axiomatic system.
Those concepts are related in a few very succinct algebraic formulas. You can use calculus to show how they interrelate, and these are called the laws of the theory. It has a ton of explanatory power.
Another thing is that the exceptions are choices that you make. You might say, "Well, I'm gonna ignore friction. Even though I could model it in the problem as a force, I'm gonna ignore friction on this problem because I know it's gonna be insignificant." You're choosing to ignore stuff in this model.
You can always add stuff. People add stuff like hydrodynamics and other stuff that's added on to this basic billiard ball system. It's not like modeling shapes and things like that, because those aren't important if you're on a frictionless plane, like the model shows.
It's not the real world, that's for sure. It is an idealized system that still has a lot of explanatory power.
All that is to say that you cannot refactor Aristotle into Newton. Newton is not just a cleaned up, "Let's organize the code, rename things and make it clearer. Make it beautiful, clean code." No, it is a totally different model that is incompatible at a fundamental level.
This is also true in our software systems that there are different abstractions that are not compatible with each other. You couldn't refactor one into the other. It's not just a matter of cleaning it up.
Refactoring which is defined as changing the structure of your code without changing the behavior. You need to change the behavior of your code to move from something like Aristotle to something like Newton.
What that tells me is that the choice of abstraction is much more important than having clean code, because cleaning up code, we know how to do that. It's just moving stuff around, it's renaming stuff, it's making it neater, we just clean it up.
Changing the behavior is a totally different animal. It requires, especially if your abstraction is deep in the core of your software, changing the abstraction will require a lot of surgery. It will not be easy. You're going to have to be pinching off arteries that are gushing and it's not going to be an easy task.
My whole thing is that — like I had in the last episode — the core abstraction, is something that can give you a business advantage. It's not something that you can just arrive at with a million user stories, even if they're the right user stories.
User stories might be good for modifying existing software that has good abstractions at the core, because what you're doing is simply adding on different UI elements or changing the UI. If you got the wrong abstractions at the core, you're not going to be able to capture that advantage. You're not going to be able to clean up what you got to make it more like what you're looking for.
What you really need is some kind of leap like from Aristotle to Newton where you got something that's a mishmash of concepts with mostly corner cases to a unified model, so that you can actually rely on it, and something as simple as possible to give you the properties that you need to solve your problem.
Tell me what you think if you agree that this is an interesting idea, or if I'm simply making an analogy between two things that aren't really related.
To me, this is the main thing that I like doing is going in, figuring out where the abstraction is, what's the important stuff, what properties need to be preserved, and creating a model in the software that is elegant, because everything's going to be piled on top of it.
How do you that? How do you get in there? How do you extract out this model from the...It's really from the domain. You don't extract it out from the software. Like I said, you can't just clean it up.
You have to come in, use the version they have as a prototype, consider it like, "You've proven that there's a market, you've proven that this is possible to do, but let's learn a little more about the domain and really do this right the first time."
If you like what you've heard, if you don't like it, if you disagree, I really love having discussions with all my listeners. You can contact me on Twitter. I'm @ericnormand, and I'm also firstname.lastname@example.org via email.
Like and subscribe. Share with your friends, because sharing is caring. All right, see you later.