This is MarianSchubert's Typepad Profile.
Join Typepad and start following MarianSchubert's activity
Join Now!
Already a member? Sign In
MarianSchubert
Prague, Czech Republic
Programmer with passion for his craft. Constantly trying to improve.
Interests: albumino.com, coderetreat, photography, motorcycles
Recent Activity
We have tried pretty much all the things you mentioned in the first part of your article - refactoring stories, refactoring iterations, doing refactoring before/after/during task or story. All of them with mixed results. Our product is old legacy system written in Perl so you can imagine that there are a lot of opportunities to refactor. We also have quite a few constraints. Biggest one is that our team is pretty small compared to our product and each story touches different part of the system so we need to perform only refactorings we really need. Otherwise we wouldn't get anything done. Anyway - as you state in the article, big part of the problem is to decide _when_ to do these refactorings. Problem with refactorings which happen before feature-delivering-task is that most of the time we don't really know what's really essential to refactor in order to implement desired functionality easily in later task(s). Each time we do this during planning I feel like fake oracle trying to predict future. :) I have been trying to find a solution to this problem for quite some time. Then I found this thing called "Mikado method" http://mikadomethod.org and for the last few months I have been using it pretty rigorously for most of my work. How does it work for me? During planning we only create tasks which deliver (parts of) desired functionality. When I take task like that (let's call it feature task) I don't start coding like usual e.g. with clean/working code in mind. I just use naive approach and _try_ to implement given feature and than I throw all my changes away. During this phase I'm taking notes about problems which make finishing feature hard or impossible. Because I'm writing code that I'm going to throw away I can use some pretty nasty tricks e.g. "do I need this function to return data in some other format? no problem - I just modify it or even return fake static data.". At this point I don't really care that it will break every other place which uses this function. I just take note that this modification has to be done before actual work starts on feature task. Then I throw code which I just wrote away. I review my notes with problems and if there are just few simple ones I start to implement them and push commits with these refactorings. When I'm done I try to implement feature again and if everything goes OK than it's just one (usually pretty simple) commit. And it feels like code has been designed to accept features like this. When I find bigger problems I write each of them on task card and put them on board so that any of my teammates could help me with them. It's common that these tasks could be done in parallel as most of the time they touch different parts of the codebase. For these bigger problems I apply "Mikado method" again as it's possible that they would also require some pre-refactorings. When I find really big problems it's easier to talk about them with the team and decide whether to continue or limit scope of the feature so that it could be implemented in reasonable time. So far I'm really pleased with this method as it provides me a lot of benefits. Few of them are: 1. no more guessing what to refactor 2. goal (feature) oriented 3. commits are simple (as they don't contain multiple unrelated changes) 4. at no point I'm pushing bad code into codebase - just improvements and final implementation of the feature 5. it's easier to zoom out to see where I'm and what needs to get done PS: Your book "Working Effectively with Legacy Code" helped us quite a few times so thanks for it :)
Toggle Commented Jan 16, 2013 on Refactoring is Sloppy at Michael Feathers
MarianSchubert is now following The Typepad Team
Jan 16, 2013