D2H: Legacy
Notes from RailsConf Europe presentation
“Legacy ain’t so bad.”
Some of this stuff is notes to myself, rather than what he said.
“There’s no other way to consistently learn and become better than to write a whole lot of legacy software.”
Legacy is a feeling. Code that was “best code ever” becomes “eww,” without the code changing at all. You changed, not the code.
Don’t start over. Rather than rewriting file by file, just leave code better than you found it. When you are working on a bugfix or new feature, improve the code that you’re touching. Think about it as if an app has a bunch of garbage cans lying around. When you have to use something with a garbage can, just pull out some of the trash, and sort it.
Legacy should be a good feeling. When you look at code and think “REWRITE!!!” it means that you’ve learned a lot. All code you write is already legacy in some ways, and it will certainly be a month from now.
Use this feeling to learn, rather than to feel imprisoned. If you never write legacy code, that means you’re not learning. This is not an excuse to write bad code. Obviously, write the best code you can know but understand that it will become legacy.
Learn from this. Don’t rewrite from scratch, instead, if you see a “garbage can” like application helper, ask yourself why this happened. Why is there so much crap here? For application helper, it was because there was no helper :all. So, the issue was that you didn’t have a place to put things that would be used across multiple views. So instead of just rewriting, you realize a pattern. Don’t just delete entire files when rewriting. Keep application helper as a staging area.
Work on projects that matter, that can take 10 years to write. Don’t hop from project to project, work on the same few things. Stay around to watch applications turn legacy. That way you will see the patterns, and develop a toolselt to “dial back the clock” on how it became legacy.
Things grow over time. There ends up being a lot of stuff that is important to what the thing does, but isn’t core to what it is. You end up with garbage cans in models.
Extract concerns. When you have garbage cans in your modules, extract pieces into “concerns,” which are modules. So, if you have a bunch of crap about system notices, pull into into a notice.rb module, and include it in user.rb. Sort the trash. Put these modules in a folder with the name of whatever the model you’re including them in. Concerns are not about reuse. If it’s something reusable, put it in lib. (Obviously, don’t write things to be reusable in all cases, or you are enterprise)
Treat global stuff as train stations. Put stuff in app controller, or ap helper only until you can find somepalce better, don’t leave stuff there for a long time. (Personally, i just delete app helper in my apps and just make a new module even if it only has 1 method)
A system that’s too DRY is hostile to changes. You start out with a DRY notion, and “something that used to be lovely and DRY no longer is. Dryness ends up with a bunch of nasty exceptions.” If you have a view with a ton of ifs and unlesses, just copy the whole thing and only deal with a specific version. Sometimes have a little bit of duplication makes the fabric of your software more flexible.
You end up at dry when you have too much duplication, but then you realize that things are too dry, and you break it out a bit more. “I just want to change one thing”
If you get too attached to what you think is best right now, you’re just setting yourself up for doing that very shortly again (is this a bad thing?)
Don’t encapsulate render calls in helper methods. It makes it hard to see how partials fit together. You end up not knowing “how do I get to this one thing I want to change.”
Doing things like having both “index.html.erb” and “_index.html.erb” is an example of what seems like a good idea to improve legacy, but then it becomes maybe even worse than the original legacy code , in this case it’s underscore means.
Extract methods into modules that reveal their own intention.
Even in 37signals old code, most of their methods are still only 1-4 lines. Most are 1 or 2.
December 12, 2008
