The software development community contains a huge amount of litterature with advices on how to “do” things. Do’s and dont’s are littered across the Internet – to be true I’ve also given birth to a few posts myself on various topics from time to time. Browsing the stuff one has written in the past can be quite an eyeopener in terms of “I-must-have-been-drunk-writing-that-piece-of-insanity-and-publishing-it-to-an-audience”… Any blogger with a decent record of blogposts across time probably has similar emotions towards their own blogposts otherwise you’re doing something wrong, I believe. You’re not learning anything and you’re definately not making enough mistakes on a daily basis. Only if you (such as myself) are doing regular f***ups on production environments and is the proud owner of www.iwanttoshootmyselfwithaslingshotforhavingreleasedthat.com – only then you’re in a position to discover new things about coding and yourself – and only then will you be able to reflect quitely upon the fact that truth is relative. What you believe today might not be what you believe in after another day at work tomorrow.
So – with that in mind it’s important for me to elaborate a bit from time to time over what I believe are rock-solid facts right now. Not tomorrow because I’ll probably screw up two or three times tonight during release and spend a few hours firefighting something which could have been avoided had I decided otherwise somewhere along the line. Then in a few years I’ll be able to look back on this post and think “Did I write that? Man, what a n00b…”.
As for now I want to tell you a bit about my thoughts on refactoring, how I think it should be done and the pitfalls I’ve fallen into while refactoring. Martin Fowler has written an almost mythological piece on refactoring and his Refactoring website is a good place to visit because there’s always new things to learn. Here goes
1: As always: Learn the basics, in this case about OO. If you don’t know the very basics such as “High coupling is bad” and don’t know when your code could benefit from an interface you won’t be able to recognize bad code from good code. Refactoring isn’t supposed to shape the code into something you alone like – that’s simply a waste of time. The overall goal is to improve overall readability and lift the quality of the code in terms that can be measured by tools such as FxCop and NDepend.
2: Refactoring is something you always do. Renaming a variable is refactoring – you don’t have to extract duplicate code into a method to qualify what you’re doing as “refactoring”. That’s also why agile tells us that “refactoring” tasks on the Sprint board is an antipattern. You should be refactoring 50% of the time while coding otherwise you’re doing something wrong.
3: Iteration, selection and statements – every line of code you’ve ever written has either been an iteration over something, a predicate or a statement. You can be aggressive refactoring iterations and statements because that’s often not very dangerous. Iterations and statements are changed when we rename and change visibility of methods, put duplicate code in base classes, replace magic numbers, consider recursion etc. That’s often not something to be afraid of. Changing behaviour however is a whole other story. You consider changing behaviour when you look at a monster of if-elseif-elseif-elseif…[snip]…else something and decide to introduce i.e. a Strategy Pattern. You also might go for refactoring that hideous substring-replace hell someone before you introduced to parse HTML strings because you know your Regular Expressions to the fingernails… I urge you to go for it but take your time writing those unittests. The reason you’re refactoring selections is that they are too complex for the average programmer to understand which is a proof to the fact that you probably don’t fully understand what the code is doing. How much of a moron are you if you actually think you can rewrite 100 lines of code you don’t understand into something smaller, prettier and still with the same behaviour intact? You can’t unless you really know what you’re doing (which you don’t) – and it is just a pain to have to explain to people on the floor why invoices are suddenly being sent twice to the wrong address because you missed something during your rewrite.
4: If you’re a C# programmer and have a pile of public methods you think nobody is using anymore – you can do three things: Delete, check in and pray. Or you could leave the methods as-is. Neither option is very good – you should deprecate the method instead and see if warnings start to pop up in other solutions. The [Obsolete] tag in C# is a tremendous efficient way of figuring out if public properties / methods / classes are being referenced anywhere outside your code. It’s perfectly safe and you can always go back and delete whatever you marked as Obsolete when you have made certain that there are no warnings appearing around your codebase.
5: Use tools. You’re not smart enough anyway. I know myself well enough to not trust myself at (almost) anything regarding code. Tools don’t lie – you ask, they respond. Ask WinGrep “I want to find .cs and .aspx files which contains ‘SomeNamespace.IWant.ToFind'” and it will find them for you. If you’re busting your brain to figure out assemblies where a piece of code could be used you should be using a tool to help you. The human brain is by far the most unreliable computer there is. You and all of the human race suck at being 100% accurate – that’s why man has built computers with software for you to use, damn it… I’ve only scratched the surface of NDepend but it has helped me already by clarifying some assumptions I had about our current codebase at work.
6: Don’t forget code readability. It’s not something which will improve your Cyclomatic Complexity level but it’s so important to be able to read your code. Really read – like a book. Your goal while programming should be to become the new Stephen King - in code. Or if a big guy with a beard from Hell is what turns you on you could always go for Martin Fowler. I’ll leave the details up to you. Beautiful code is easy to read and reveals intent. A fair amount of the refactorings suggested on Fowlers www.refactoring.com does indeed push for simple things such as renaming because readability in code is vastly underestimated as a code quality metric.
7: Know when to quit. You can keep on refactoring the same code because code isn’t perfect and can always be improved. Your choice and plans of attack changes over time because you change and mature as a person (hopefully). You can easily refactor the same piece of code over and over again over the years without improving it very much if you don’t look out. Ask yourself if it’s worth the effort. If it’s not ask yourself if you could learn something new by refactoring this piece of code. If not – ask someone if you should go for it. If that someone doesn’t nod his or her head – focus your energy elsewhere.
Until later…
Ingen kommentarer:
Send en kommentar