Showing posts with label change. Show all posts
Showing posts with label change. Show all posts

Friday, February 3, 2012

There Is More To Clean Code Than Clean Code

A post written by Uncle Bob in January (I'm behind my reading list) offended me. I absolutely agree with Uncle Bob's analysis regarding the code itself, and I also prefer the refactored version, but I have a problem with insulting the programmer(s) reluctant to appreciate the change.


We write code in programming languages, and there are different levels of proficiency in a language.


As I'm currently learning a new spoken language, I'm painfully aware of this - initially I probably sounded like a caveman. The first impression you get about me is totally different depending on the language I speak - but I am the same person!


The learning curve of a language is not smooth - the steepness between consecutive levels of proficiency is different. Going from not speaking any German to speaking A1 (tourist) level was easy, getting the basic grammar required for the low intermediate (B1) level wasn't too bad, but to get my German to the level where my English is will take more effort than the sum of all my previous investments1.


Since it is my third foreign language I'm learning, I have no difficulty accepting that the level I think I speak is higher than the level I actually speak. Because of that, whenever someone rephrases my sentences in proper German 2, I start from the assumption that likely their version is better, even if I don't understand first why - and I take the effort to understand their reasoning 3. I do that despite that I was of course convinced that when I spoke, I expressed my thoughts in the best possible way.


However, I don't have much at stake - no ego to hurt, no reputation to loose, and the roles are clear: I'm the beginner, and the people around me are the more experienced ones. In a software team, the roles might not be so clear - I had told colleagues almost twice my age how they should write code after only a few weeks of working there. Bad idea. Since then, I have learned not to start improving the coding style of a team by rewriting the code they have written, and showing off how much better my version is. Rather, I wait until a situation arises when they don't mind having me demonstrate some code improvements. I demo it, and explain why I do it that way. In my experience, the second approach is more effective, though it doesn't have that instant satisfaction and relief the first provides.


As the joke goes, you need only one psychologist to change a light bulb, but the light bulb has to want the change real bad.


Driving Technical Change is hard, because it requires a mental/cultural change, and that change has to come from the inside - but can be catalyzed from the outside of course4. But just forcing practices or ways of working on unwilling recipients generates resistance (e.g.: the story of the EU technocrat appointed to recalculate the 2009 Greek budget).


I would like to see more public code reviews and public refactorings (e.g.: Andrew Parker, GeePawHill), but I would like to see less public judgement passing on people at the lower proficiency levels of programming.




1 there is a great Hanselminutes episode on learning a foreign language if interested. Beware, it may contain programming!


2 German readers might disagree, since most Germans I meet speak Frankish :)


3 Which of course, is sometimes harder for natives to properly explain than for novices to ask questions pointing out the seeming irregularities of the grammar


4 And we won't always be able to foster change in all environments (note: this does not mean the others are at fault for not changing!). The same programmer can be highly productive in one team, and be the one slowing down another team. There is nothing wrong with changing jobs after realizing we are a net loss to a given team.

Sunday, May 15, 2011

On Grassroots/Peer TDD Introduction

While I'm no trainer/coach, I've been involved in spreading TDD among my peers, with varying extent of success. Recently someone asked for advice on how they should go about it, and in the spirit of Seth Godin, instead of responding in a private email, I wrote this post, a mix of experience and hindsight ideas.


So, we are one (or two) developers in the team/company, already sold on TDD, with some unit testing experience. The peers are willing to listen to the concept, and management, while not willing to invest in formal training, is ok giving a chance, as long as it doesn't hurt the projects' performance. How do we go about it?


Don't introduce TDD on the project


It's common that teams learn/practice new skills on live projects after a basic overview/training. While this might work, I would not recommend this approach for any grassroots initiative, because the chances of failure are significant, and one bad experience with a practice/technology can doom any further attempts to introduce it later, even if not the practice was at fault, only was applied without enough practice. A project manager friend of mine recently complained to me that since the team that worked on a massive legacy project started doing TDD, tasks that used to take hours begun to take days, and clearly, he wasn't happy about that. It turned out that the problem wasn't due to TDD, but lack of discipline (developers went overboard with refactoring, touching parts of the codebase not even remotely connected to the task they've been working on). Despite this, he could have easily come to the conclusion that TDD equals to dropped productivity, without much benefit (bug reports kept coming in, even if for different features - we are talking about legacy code!). Any new skill has a learning curve, you will be slowed down, and you won't get it perfect the first time - don't give a chance for the others to associate failures with the new concept. If you are like me and would need a more concrete example about refactoring just enough, I suggest you read Ron Jeffries' Extreme Programming Adventures in C# book, and on advice for dealing with legacy code, the undisputed classic book is Michael Feathers' Working Effectively with Legacy Code.


Introducing/selling TDD to the other developers


A lot of technical presentations focus on the how instead of why it is beneficial to the audience. When it comes to TDD, I would also suggest presenting it simple - skip the emerging design concept (some of the early advocates noted that good design emerging from TDD might had to do with the fact that those early advocates actually had great design sense anyway), don't mention YAGNI - in short, don't overload them with new concepts. I rather liked the approach Paul Butcher took in his Debug It! book - we tend to program one baby step at a time, articulating in our mind what the next behavior we'll implement should be, then we code it, and move to the next behavior. TDD (or Test First Development for the nitpickers :)) is just a minor step from that, i.e.: we actually write down the articulated concept in code (which we tend to do anyways with the throwaway main methods used for debugging). And in addition, we get an automated regression test suite for free :). While a live demo could be cool, I would probably show one of the Kata casts instead of me typing on the projector. Also, be sure to point out that at first we won't be able to code at this speed (I still can't)!


Learning/practice


TDD is a rather simple concept, but so are all the great wisdoms - it takes a lot of time and experience to fully understand those concepts. After the initial TDD sales pitch, I would dedicate a session to going over the tools and the basic usage - how to install the test library, how to run the tests, how to debug a single test, and the basic assert statements - AreEqual vs. AreSame, Assert.Throws, and also an example to show that most likely there are more asserts in the library (e.g. StringAssert.EndsWith).


With those interested/committed, we can move on to the supervised practice step. We've worked on simple problems, in a structure inspired by this Peer learning presentation by Jason Gorman (his site even has a full case study of this applied at the BBC). The coding dojo is another possible format. Important thing is discuss the experiences, lessons learnt, and problems overcome with the whole group, because while practice makes one perfect, bad, practiced habits are hard to unlearn. It is OK not to have all the answers - just be ready to admit it, and ensure that you can find it out from somewhere. Meetups, user groups, and similar forums are invaluably helpful.


Be sure to eat elephant in a piecemeal fashion - while at first the simple problems seem contrived, don't attempt to practice testing existing, complex production code. Stick to the simple problems for practice, every now and then actually demonstrate that it is possibly to test legacy code (though it'll require quite some preparation from you), maybe have some of these examples as a group exercise, but be sure to keep the practice focused on the simple mechanics initially. Just like any sport practice - you repeat rather basic exercises over and over, because it does pay off in the long run, but to keep you motivated, you do have the free practice sessions too.


Don't force it


Not everyone has the same passion as you do (you must have if you read this far :)), and some take a longer time to learn, have different pre-existing concerns they should overcome. Lead by example, be available to talk about it, answer questions, clarify, but don't try to force it on them. Urban cycling didn't became popular because we, cyclists, were preaching to pedestrians and car drivers - we were just approachable to friends, coworkers, etc. and provided answers and listened to their concerns. Yes, it could take a long time, but patience pays off - self-motivated people are more likely to overcome the hurdles they inevitably will face in the learning process!


Bringing it to production


I wouldn't set strong rules or hard deadlines like "two months from now, you all must write all production code in a TDD fashion", but rather just tell people to feel free to experiment during their daily work, but ensure they don't confuse work and practice. If they get stuck on testing some problem, they should just make a note, and deliver the feature untested, as they used to do before. Later, together with the group they should discuss it and potentially find a way to test it.


Further resources


This post is just a high level overview, and I have simply glossed over many of the actual difficulties about writing good unit tests, keeping them maintainable, etc.. There are books written about the topic, in almost all programming languages. Coming from a .NET background, I can recommend The Art of Unit Testing with examples in .NET by Roy Osherov, and I've found James Shore's Let's Play TDD Java episodes great - the best thing about the latter is the thought process narrative that goes with it. Driving Technical Change might be another good book, though I haven't yet read that.


Good luck!