The confessions of a refactoraholic
Tuesday, June 5, 2012
Architecture according to Uncle Bob
"a good architecture maximizes the number of decisions NOT made"
Friday, May 4, 2012
The nightmare of refactoring
I am watching the series "Clean Code". Episode 6 on Test Driven Development describes a nightmare scenario for refactoring that is so close to heart, that I just have to quote it here.
"Have you ever brought up some code on your screen that was ugly? And the first thought through your head was, 'Wow this is ugly, I should clean it'? And the next thought in your head was: 'I'm not touching it'. Because you know if you touch it, you'll break it, and if you break it, it will become yours"
"Sometimes the mess gets so bad, that we contemplate a dedicated effort to clean it... At first our employers might even support this idea. ... But cleaning code is hard and fraught with risk. When we clean a module, we have no way of knowing that that module still works properly. Perhaps we've introduced subtle bugs, or race conditions, or data corruptions. The more we clean, the riskier the situation becomes. The ad-hoc manual tests we've been running to make sure that the system behaves properly, begin to fail for reasons we can't easily explain. We start to debug and the debugging time grows, and as it grows, it eats into the time we thought we'd have for cleaning. After weeks of cleaning and debugging, we finally run out of time, and although we've done a lot less cleaning than we wanted to, and a lot more debugging than we'd hoped, we think the system is at least a little bit cleaner. So we hand the new "cleaned system" to QA... And unfortunately they return with a huge pile of defects. These defects are daunting, they contain inexplicable behaviors, data corruptions, even crashes. The list of new defects is so long and so puzzling, we don't even know how to estimate
how long it would take to repair it. After much wailing and nashing of teeth, we finally conclude that the only sane action is to set the "clean system" aside, and to revert to the pre-cleaned state. "
"And so we're stuck with a mess that we're too afraid to clean. Our estimates grow with every passing year, our productivity continues its asymptotic plunge toward zero, and yet we're helpless to do anything about it, paralyzed by our fear
"Have you ever brought up some code on your screen that was ugly? And the first thought through your head was, 'Wow this is ugly, I should clean it'? And the next thought in your head was: 'I'm not touching it'. Because you know if you touch it, you'll break it, and if you break it, it will become yours"
"Sometimes the mess gets so bad, that we contemplate a dedicated effort to clean it... At first our employers might even support this idea. ... But cleaning code is hard and fraught with risk. When we clean a module, we have no way of knowing that that module still works properly. Perhaps we've introduced subtle bugs, or race conditions, or data corruptions. The more we clean, the riskier the situation becomes. The ad-hoc manual tests we've been running to make sure that the system behaves properly, begin to fail for reasons we can't easily explain. We start to debug and the debugging time grows, and as it grows, it eats into the time we thought we'd have for cleaning. After weeks of cleaning and debugging, we finally run out of time, and although we've done a lot less cleaning than we wanted to, and a lot more debugging than we'd hoped, we think the system is at least a little bit cleaner. So we hand the new "cleaned system" to QA... And unfortunately they return with a huge pile of defects. These defects are daunting, they contain inexplicable behaviors, data corruptions, even crashes. The list of new defects is so long and so puzzling, we don't even know how to estimate
how long it would take to repair it. After much wailing and nashing of teeth, we finally conclude that the only sane action is to set the "clean system" aside, and to revert to the pre-cleaned state. "
"And so we're stuck with a mess that we're too afraid to clean. Our estimates grow with every passing year, our productivity continues its asymptotic plunge toward zero, and yet we're helpless to do anything about it, paralyzed by our fear
Friday, March 9, 2012
Give praise to your fellow programmers
I have been working on top of a code base set up by another guy. As I went thru the code, again and again, I got the feeling that it was well written and well designed, unlike so much other crap I see out there. It gave me "trust" that the code was doing what it was supposed to for the most part, and that the design decisions were sound, as well as an easy way to extend the code base.
In an act of kindness I decided to send an email to the original coder thanking him for good design, specifically outlining what I thought was good, so he knows I mean business. Pretty gay, you might say. Well gay or not, I think the guy needed to hear it, and he was very greatful for the praise.
I also realized that in my many years of coding, I only heard direct praise about some particular thing I did in the code only once or twice.
This just got me thinking how in the programming world it's so rare that we praise other people's code, and that's pretty sad. On the other hand, we do waaay too much bashing of other people's designs and coding abilities, behind their backs, or worse yet, in their face. Nothing wrong with constructive criticism, except it tends to be unconstructive for the most part. So there's some kind of mucho culture in existence that prevents us from giving each other props on a job well done.
Next time I work on a code base where I realize the guy put in some effort to make it easy for the next person, I'll make sure to mention it to them. You should do the same.
In an act of kindness I decided to send an email to the original coder thanking him for good design, specifically outlining what I thought was good, so he knows I mean business. Pretty gay, you might say. Well gay or not, I think the guy needed to hear it, and he was very greatful for the praise.
I also realized that in my many years of coding, I only heard direct praise about some particular thing I did in the code only once or twice.
This just got me thinking how in the programming world it's so rare that we praise other people's code, and that's pretty sad. On the other hand, we do waaay too much bashing of other people's designs and coding abilities, behind their backs, or worse yet, in their face. Nothing wrong with constructive criticism, except it tends to be unconstructive for the most part. So there's some kind of mucho culture in existence that prevents us from giving each other props on a job well done.
Next time I work on a code base where I realize the guy put in some effort to make it easy for the next person, I'll make sure to mention it to them. You should do the same.
Friday, January 13, 2012
The Mythical Man-Month quote
In many creative activities the medium of execution is intractable. Lumber splits; paints smear; electrical circuits ring. These physical limitations of the medium constrain the ideas that may be expressed, and they also create unexpected difficulties in the implementation...
Computer programming, however, creates with an exceedingly tractable medium. The programmer builds from pure thought-stuff: concepts and very flexible representations thereof. Because the medium is tractable, we expect few difficulties in implementation; hence our pervasive optimism. Because our ideas are faulty, we have bugs; hence our optimism is unjustified. [The Mythical Man-Month, by Frederick P. Brooks, Jr, page 15]
Monday, December 12, 2011
Resharper: a refactoraholic's dream come true
So I recently discovered Resharper, and it's a refactoraholic's dream come true. Most of the tedious routine tasks are now automated, just the way they should have always been. Why oh why God did you make me wait so long for this miracle? Why did I have to waste countless hours doing manually what was always meant to be done automatically?
Not sure if your field is used from anywhere else? Resharper already knows and suggests before you may even wonder. Is your naming scheme consistent? Resharper will tell you all about it. Apparently you can even apply a solution-wide code analysis, which I haven't yet tried, but it sounds promising.
It may seem a bit intrusive, popping up with suggestions all over the place, but it works for me, so far most of the suggestions have been very sensible, and it definitely beats the shit out of Visual Assist. Oh and it provides a Unit Testing framework too, while it's at it. Not too shabby.
Not sure if your field is used from anywhere else? Resharper already knows and suggests before you may even wonder. Is your naming scheme consistent? Resharper will tell you all about it. Apparently you can even apply a solution-wide code analysis, which I haven't yet tried, but it sounds promising.
It may seem a bit intrusive, popping up with suggestions all over the place, but it works for me, so far most of the suggestions have been very sensible, and it definitely beats the shit out of Visual Assist. Oh and it provides a Unit Testing framework too, while it's at it. Not too shabby.
Thursday, December 1, 2011
Good management vs. bad management
In my relatively short career, I have seen a LOT of bad managers, and relatively few good ones (one of the readers of this blog included in that). The subject has always interested me immensely, since a manager, often to a much greater extent than any of the people that work for him, determines the success or failure of a project. So what are some of the skills that make a good manager?
Area 1: People Skillz.
A good manager is good with people, at least to the extent that the job requires it. You don't have to be a social butterfly, but you gotta be able to talk to people about what's important. The other important factor here is alpha-ness. It's about being able to ask things of people in a way that would motivate them to take action. It's also about being able to stand up to criticism from higher-ups and insisting on what's right. You need to muscle your way thru opinionated people and convince others of the merits of your case, whether it be on technical grounds or sales numbers, or just plain common sense. You need to know how to make people listen.
There is also the flip side to that. I have seen too many managers who are too alpha. That means they're too dismissive of their subordinates, they don't listen enough, and they trust their gut instinct too much at the cost of proper decision making. The uber-alpha manager always thinks he/she got things under control, which can be a bad thing (see Area 5). Being too alpha can also mean demanding the impossible. ("We have to do finish this 5-month long project in 1 month and we have to do it perfectly"). Demanding the impossible and not listening enough will also mean losing the respect of the subordinates, who will not take you seriously, or despise you for wasting their time.
Area 2: Responsibility a.k.a. giving a shit.
This is a big one. It sounds obvious, but I've seen too many managers lacking passion for the project they're working on. If a manager only cares about having the burndown chart go to zero, or meeting the deadline without getting into the details of what that would really mean, he's a lazy fuck and needs to get some sense knocked into him (which would require someone above to detect the laziness and take action). The manager who doesn't give a shit, will never take responsibility for the project going wrong. The deadline slipping is always the fault of somebody else, "I was watching the burndown chart, and it looked like we were gonna make it, and then Bob put in this extra task at the last minute, so we failed because of him." This type of statement is usually followed up by some hand-waving: "But don't worry we're gonna make it anyway". The irresponsible managers also tend to socialize with each other at the cost of the team, to give each other a pat on the back when everything goes to hell. A responsible manager admits failure when it happens, and, what's more important, is going to try to do better in the next iteration. It's about the self-improvement attitude. Unfortunately, it seems like some managers are in it for the Manager at the XXX Corp title. Once they got the title, their job is done. I know I'm being silly, but sometimes it feels like that's how things work.
Area 3: Time Management
This is the classical thing they teach in school and is covered extensively in books. How to manage your time and the time of your team. How to do project planning: estimates, burndown charts, how to handle the complexity of a project. Unlike Area 2, this is not a personality trait, but a skill, and most managers tend to have some idea what to do here. The problem comes later when (surprise!) the estimates don't reflect reality and something needs to be done. The manager inevitably needs to get into the details, as time management skills in and of themselves will only get you so far. This skill can improve with (management) experience.
Area 4: Technical Skillz and having a clue.
You need to be able to know what the hell is going on. An art manager needs to know something about art, a programming manager needs to know something about programming. You need to know what estimates make sense for a particular employee or department.You need to know when people are throwing dust in your face, or (when they're throwing dust in their own face). This bullshit-detector cannot be purchased at Walmart, and comes only with (technical) experience.
Area 5: Knowing Where the Project Is and where it needs to be
It's about really having a clue whether the project is 6 months from completion, or if it's 5 years away (as well as knowing what "completion" really means). Sounds easy, but this is the area where most of the bad managers I've seen failed completely. At least in the few places where I've worked, managers seem to get into the state of denial with unprecedented ease. Often an indicator of a manager who is bad at Area 5 is the following situation: when they declare a deadline, everybody on the team immediately knows they're not going to make it. The manager himself will continue insisting that that's where the deadline is and the scope won't change, until it's too late. You can blow dust in people's face, but you should always know that you're doing it and not kid yourself about making a deadline. The deadline is important, but just as important is the scope. What is it that is going to be delivered? What kinds of adjustments would need to be made to still make the deadline even though not everything is done? What kinds of corners can be cut, and what kinds of corners are too expensive to cut? Does the deadline need to be postponed? If so, will it be just one more week, or are you just kidding yourself again? You can SAY it's one week to sell it to the customer, but you need to know you're lying for your own sake.
Area 6: Knowing HOW to take the project where it needs to be
Area 6: Knowing HOW to take the project where it needs to be
This is about knowing how to take a project from A or wherever it is to Z, the final deliverable. It will take all of the above skills together to achieve that, and no wonder good managers are hard to find. It's a tough job, but somebody has to do it.
Tuesday, October 4, 2011
Refactoring and code ownership
So I've been given a pretty big chunk of Perl code to work with. It's about 30 pages of pure hell, all in one file, and considered unmaintainable by some. Of course the word unmaintainable is not in my vocabulary (and apparently not in Blogger's dictionary either), and somebody had to do the job, so the Refactorinator comes to the rescue.
At the surface level, refactoring Perl code is not that much different than refactoring C++.
OK, I realize there's nothing Perl-specific here, I guess I'll have to make another post about that. But perhaps the lesson I'm learning here is refactoring is pretty universal, as long as the language supports multiple files, struct-like constructs, and basic functions.
Am I regurgitating basics here, being Captain Obvious? Maybe so, but then if the principles and techniques I'm writing about are so basic, then why the hell do I so consistently come across code with exactly the same mistakes time and time again? The short answer is "up front cost". That's a cost a lot of people are hesitant to pay, especially if there are ownership issues:
At the surface level, refactoring Perl code is not that much different than refactoring C++.
- Identify groups of variables that belong together, and group them into chunks / structs, that can be passed around between files and functions without creating too much clutter.
- Break up the monster functions into smaller functions. Passing data between functions should be easier because of step 1
- Break up the monster file into multiple files, and hopefully never look at some of these files again. Hopefully at this point, we have arrived at some self-contained functions (step 2) with relatively short function signatures (step 1).
OK, I realize there's nothing Perl-specific here, I guess I'll have to make another post about that. But perhaps the lesson I'm learning here is refactoring is pretty universal, as long as the language supports multiple files, struct-like constructs, and basic functions.
Am I regurgitating basics here, being Captain Obvious? Maybe so, but then if the principles and techniques I'm writing about are so basic, then why the hell do I so consistently come across code with exactly the same mistakes time and time again? The short answer is "up front cost". That's a cost a lot of people are hesitant to pay, especially if there are ownership issues:
- Code has no clear owner - why should i clean up somebody else's code?
- Code has an unfriendly owner - your cleanup is very much unappreciated, because the owner a) thinks refactoring is a waste of time or b) has a big refactoring plan in mind himself, which he'll probably never get around to, but in the meantime you shouldn't ruin his grand plan
- Code has another owner - even if he's friendly, why should you do his work.
- Code has an owner that doesn't believe in refactoring
- Code has an owner that believes in refactoring in principle but never gets around to it in practice
Subscribe to:
Posts (Atom)