<?xml version='1.0' encoding='UTF-8'?><?xml-stylesheet href="http://www.blogger.com/styles/atom.css" type="text/css"?><feed xmlns='http://www.w3.org/2005/Atom' xmlns:openSearch='http://a9.com/-/spec/opensearchrss/1.0/' xmlns:georss='http://www.georss.org/georss' xmlns:gd='http://schemas.google.com/g/2005' xmlns:thr='http://purl.org/syndication/thread/1.0'><id>tag:blogger.com,1999:blog-10784478</id><updated>2012-01-27T01:21:19.696-08:00</updated><title type='text'>Vlad's Agile Software Development Blog</title><subtitle type='html'></subtitle><link rel='http://schemas.google.com/g/2005#feed' type='application/atom+xml' href='http://vladimirlevin.blogspot.com/feeds/posts/default'/><link rel='self' type='application/atom+xml' href='http://www.blogger.com/feeds/10784478/posts/default?max-results=100'/><link rel='alternate' type='text/html' href='http://vladimirlevin.blogspot.com/'/><link rel='hub' href='http://pubsubhubbub.appspot.com/'/><author><name>Vladimir Levin</name><uri>http://www.blogger.com/profile/09680919094932667147</uri><email>noreply@blogger.com</email><gd:image rel='http://schemas.google.com/g/2005#thumbnail' width='21' height='32' src='http://2.bp.blogspot.com/_zD5Hp0u_Wi0/SqSQJLR_0_I/AAAAAAAAADE/l8j4ET6y63E/S220/vlad_korean.jpg'/></author><generator version='7.00' uri='http://www.blogger.com'>Blogger</generator><openSearch:totalResults>58</openSearch:totalResults><openSearch:startIndex>1</openSearch:startIndex><openSearch:itemsPerPage>100</openSearch:itemsPerPage><entry><id>tag:blogger.com,1999:blog-10784478.post-5443581016682280917</id><published>2009-11-21T08:57:00.000-08:00</published><updated>2009-11-21T08:57:04.808-08:00</updated><title type='text'>Today's Quote</title><content type='html'>&lt;blockquote&gt;&lt;a href="http://dnicolet1.tripod.com/agile/index.blog/1965243/spoiler/"&gt;&lt;i&gt;I suspect a lot of people who choose software engineering as their profession choose it mainly for the opportunity to argue, and only secondarily for the opportunity to write code.&lt;/i&gt;&lt;/a&gt;&lt;/blockquote&gt;&lt;div class="blogger-post-footer"&gt;&lt;img width='1' height='1' src='https://blogger.googleusercontent.com/tracker/10784478-5443581016682280917?l=vladimirlevin.blogspot.com' alt='' /&gt;&lt;/div&gt;</content><link rel='replies' type='application/atom+xml' href='http://vladimirlevin.blogspot.com/feeds/5443581016682280917/comments/default' title='Post Comments'/><link rel='replies' type='text/html' href='http://www.blogger.com/comment.g?blogID=10784478&amp;postID=5443581016682280917' title='0 Comments'/><link rel='edit' type='application/atom+xml' href='http://www.blogger.com/feeds/10784478/posts/default/5443581016682280917'/><link rel='self' type='application/atom+xml' href='http://www.blogger.com/feeds/10784478/posts/default/5443581016682280917'/><link rel='alternate' type='text/html' href='http://vladimirlevin.blogspot.com/2009/11/todays-quote.html' title='Today&apos;s Quote'/><author><name>Vladimir Levin</name><uri>http://www.blogger.com/profile/09680919094932667147</uri><email>noreply@blogger.com</email><gd:image rel='http://schemas.google.com/g/2005#thumbnail' width='21' height='32' src='http://2.bp.blogspot.com/_zD5Hp0u_Wi0/SqSQJLR_0_I/AAAAAAAAADE/l8j4ET6y63E/S220/vlad_korean.jpg'/></author><thr:total>0</thr:total></entry><entry><id>tag:blogger.com,1999:blog-10784478.post-5611342812523223989</id><published>2009-09-21T15:14:00.001-07:00</published><updated>2009-09-24T23:30:09.668-07:00</updated><title type='text'>Spy vs. Spy</title><content type='html'>A while ago Ravi &lt;span class="blsp-spelling-error" id="SPELLING_ERROR_0"&gt;Mohan&lt;/span&gt; wrote a&lt;a href="http://ravimohan.blogspot.com/2007/04/learning-from-sudoku-solvers.html"&gt; blog entry having to do with TDD and sudoku solving&lt;/a&gt; and I wrote a response to it asserting that &lt;a href="http://vladimirlevin.blogspot.com/2007/04/tdd-is-not-algorithm-generator.html"&gt;TDD is not an algorithm generator&lt;/a&gt;. I recently caught up with &lt;a href="http://pindancing.blogspot.com/"&gt;Ravi's blog&lt;/a&gt; and it turns out &lt;a href="http://pindancing.blogspot.com/2009/09/sudoku-in-coders-at-work.html"&gt;Peter &lt;span class="blsp-spelling-error" id="SPELLING_ERROR_1"&gt;Norvig&lt;/span&gt; indirectly referenced Ravi's original blog entry&lt;/a&gt; in an interview for the book &lt;a href="http://codersatwork.com/"&gt;Coders at Work&lt;/a&gt;. I've been thinking recently of writing a bit more on the subject of design and TDD to simplify and clarify what I said at the time so I figure I may as well take this opportunity to do so.&lt;br /&gt;&lt;br /&gt;&lt;span style="font-weight: bold;"&gt;What is Design?&lt;/span&gt;&lt;br /&gt;&lt;br /&gt;It strikes me that the big problem lies in the ambiguity of the word 'design' as it applies to programming. No one can envision how an entire application of any significance will be written ahead of time, so we break applications up into smaller problems which we can solve separately. Fundamentally that's what the word 'design' refers to: This process of cutting the thing up into smaller pieces:  You wouldn't swallow an entire 16oz steak in one gulp. Instead you cut it into bite-sized chunks.&lt;br /&gt;&lt;br /&gt;&lt;span style="font-weight: bold;"&gt;Algorithms:&lt;/span&gt;&lt;br /&gt;&lt;br /&gt;One important part of this design process is separating the algorithm from the implementation. The 'algorithm' refers to the aspect of the solution to a problem that is independent from the code you need to write. It's even independent from any specific  programming language. It's the over-all approach you're using to solve that problem. Let's say you want to write some code to fill a shape with a particular color, or sort a very large data-set, or encrypt a file, or calculate the odds of winning for a given poker hand. These tend to be the kinds of problems where you can't readily start writing code hoping to stumble toward the solution one step at a time. You have to start with some kind of plan. The algorithm is that plan. In some cases the algorithm has to be validated in a very formal mathematical kind of way. Cryptography is a good example. It doesn't matter that the average person can't &lt;span class="blsp-spelling-error" id="SPELLING_ERROR_2"&gt;decypher&lt;/span&gt; a message without the key. This kind of code generally has to stand up to a determined and sophisticated attacker and you have to know the boundaries where this algorithm will stop being effective. In other cases you just need to get the general idea and that's probably good enough to begin coding: A simple &lt;a href="http://en.wikipedia.org/wiki/Flood_fill"&gt;flood-fill &lt;/a&gt;may be a good example of that.  In fact it's often the case that you're familiar enough with a given domain that you don't need to &lt;span class="blsp-spelling-error" id="SPELLING_ERROR_3"&gt;explicitely&lt;/span&gt; define algorithms ahead of time at all. If you have enough experience you know roughly what you'll need to do and you can be confident that you'll work out the details as you go along. It's important to realize that deep down you still usually have an algorithm in the back of your mind as you begin to write code, even though you may not be fully conscious of it.&lt;br /&gt;&lt;br /&gt;&lt;span style="font-weight: bold;"&gt;Hill Climbing:&lt;/span&gt;&lt;br /&gt;&lt;br /&gt;You want to climb to the top of a hill but you've never done it before. Instead of worrying about the entire route, you pick a place up the hill you're pretty sure you can reach. Once you get there, you have a look around and decide how to get a bit father up still, etc. Instead of solving the entire problem, you come up with a simpler version or part of the problem that you have some confidence you can deal with. You write some code to solve that aspect of the problem. Then you see if you can take the next step toward a solution. You may have to backtrack several times as you go along, but this can be an effective strategy. Hill-climbing has the advantage that solving a part of a problem may make the rest much clearer, and actually working on real code can free you from the mental paralysis that can come from simply staring too long at a piece of paper and thinking really hard.  However, a hill-climbing approach can easily lead to a dead end where once you've exhausted all of the code needed to develop the fairly obvious aspects of what you are trying to do, there is no clear way to take the next step. That's where algorithmic thinking is required, and the solution, once you have it, may be conceptually different enough that you may have to throw away much of the code you wrote earlier.&lt;br /&gt;&lt;br /&gt;&lt;span style="font-weight: bold;"&gt;Where does TDD Fit?&lt;/span&gt;&lt;br /&gt;&lt;br /&gt;TDD is a technique to help you write better code. Since TDD is about the code, it's important to realize that it is generally not about helping you to develop algorithms. It's all mostly about the implementation part of the algorithm-implementation pairing at the heart of programming. That is what I meant when I wrote in my earlier post that TDD is not an algorithm generator. There's a lot more to writing an application than knowing about algorithms. Your code has to work correctly (Donald Knuth had a famous comment for a piece of code he wrote: Beware of bugs in the above code; I have only proved it correct, not tried it) . It also has to be maintainable, which means the it should readable and as self-documenting as possible, and also that it should be a free as possible from duplication.  Your implementation also has to to be reasonably efficient. If the way you implement your algorithm is too slow, that's also a problem (sometimes the algorithm itself is at fault and needs to be replaced too).&lt;br /&gt;&lt;br /&gt;TDD allows you to write code one step at a time. The general idea is that you set up some initial conditions for your test, then you call a some function (which you haven't written yet), and finally you write some assertions to make sure that function did the right thing. Having done that much, you fill in the code for that function. This type of approach lets you think about the shape of your code without the distraction of worrying about the details of how to make it work. Shaping the code is also a part of the design process, and often that's where some confusion sets in. Some people are referring to the way the code is organized when they talk about design (the classes, methods, functions, data structures, etc) and other are focusing on the algorithmic aspects. If TDD means Test Driven Design, then it's the code-shaping meaning of design that it mainly refers to.&lt;br /&gt;&lt;br /&gt;Backstopping each piece of code you write with a test allows you to achieve the following objectives: 1) Make sure your code is doing what you want it to - particularly to confirm edge cases are being handled properly; This  lets you have more confidence in the code you're writing and prevents you from having to wait 'til an entire chunk of functionality is finished before testing it to see if it actually works; 2) Assist you in thinking about how you want your code organized without &lt;span class="blsp-spelling-corrected" id="SPELLING_ERROR_4"&gt;concomitantly&lt;/span&gt; worrying about implementation; 3) Develop a regression suite that will flag changes you may make later on that break the tests 4) Provide a form of executable documentation (one that won't go stale) that will help people (including yourself!) who read the code later on understand your intentions.&lt;br /&gt;&lt;br /&gt;&lt;span style="font-weight: bold;"&gt;TDD and Hill Climbing:&lt;/span&gt;&lt;br /&gt;&lt;br /&gt;If you don't understand a problem very well to begin with, hacking code naively one test at a time is not very likely to work, as can be seen in Ron &lt;span class="blsp-spelling-error" id="SPELLING_ERROR_5"&gt;Jeffries&lt;/span&gt; attempts to solve Sudoku using that very approach.&lt;br /&gt;&lt;br /&gt;&lt;span style="font-weight: bold;"&gt;Conclusion:&lt;/span&gt;&lt;br /&gt;&lt;br /&gt;Hill climbing, writing the code so as to take one step toward the end goal at a time, works well enough when you have a pretty good idea of where you're going. However, for harder problems it's easy enough to reach a dead-end where there is no obvious next step.  Undertaking a hill-climbing approach blindly without adequate preparation means you may spend a lot of time writing code that will only lead you to an impasse.  In the domain of business programming there is not a lot of algorithmic complexity.  Most of the time the complexity in business programming arises from requirements that are often rather arbitrary and from working with large amounts of data. Developing such applications successfully isn't easy, but the difficulty tends not to be mathematical in nature:  It's more like tax law, if you will, with all of its intricacies and exceptions, than like quantum field theory. Using TDD to backstop a mostly hill-climbing strategy tends to work reasonably well for such applications.  When problems become more algorithmic/mathematical, algorithmic thinking becomes necessary. You need to consider such problems as a whole and come up with an over-all strategy to solve them.  A naive step-at-a-time approach usually doesn't work well in such cases, and it becomes necessary to work things out ahead of time.  A combination of both approaches generally works best for most applications, though the balance between the two will obviously vary from one app to another. Success in developing good software lies in the ability to find this balance.&lt;div&gt;&lt;br /&gt;&lt;/div&gt;&lt;div class="blogger-post-footer"&gt;&lt;img width='1' height='1' src='https://blogger.googleusercontent.com/tracker/10784478-5611342812523223989?l=vladimirlevin.blogspot.com' alt='' /&gt;&lt;/div&gt;</content><link rel='replies' type='application/atom+xml' href='http://vladimirlevin.blogspot.com/feeds/5611342812523223989/comments/default' title='Post Comments'/><link rel='replies' type='text/html' href='http://www.blogger.com/comment.g?blogID=10784478&amp;postID=5611342812523223989' title='3 Comments'/><link rel='edit' type='application/atom+xml' href='http://www.blogger.com/feeds/10784478/posts/default/5611342812523223989'/><link rel='self' type='application/atom+xml' href='http://www.blogger.com/feeds/10784478/posts/default/5611342812523223989'/><link rel='alternate' type='text/html' href='http://vladimirlevin.blogspot.com/2009/09/spy-vs-spy.html' title='Spy vs. Spy'/><author><name>Vladimir Levin</name><uri>http://www.blogger.com/profile/09680919094932667147</uri><email>noreply@blogger.com</email><gd:image rel='http://schemas.google.com/g/2005#thumbnail' width='21' height='32' src='http://2.bp.blogspot.com/_zD5Hp0u_Wi0/SqSQJLR_0_I/AAAAAAAAADE/l8j4ET6y63E/S220/vlad_korean.jpg'/></author><thr:total>3</thr:total></entry><entry><id>tag:blogger.com,1999:blog-10784478.post-1190786892972589415</id><published>2008-07-01T00:20:00.000-07:00</published><updated>2008-07-01T01:13:45.605-07:00</updated><title type='text'>The Problem With Popplers</title><content type='html'>Today's entry is just a rant about the state of programming in general. That's why the subject line is completely irrelevant. I was going to call it The Problem With Programming, but where's the fun in that? My problem with programming is that we keep having the same endless discussions. These discussions, in my humble opinion, are not really of much consequence. Most of the programming discussions seem to have to do with a) programming language features, b) new and better programming languages, and c) methodology. Hey, this is an "agile" programming blog, right? So I'm already guilty of c. The truth is that none of these things really matters all that much in relation to the giant elephant in the room: Competence. With reasonable exceptions, if you're competent in one programming language, you're competent in them all. Sure, you'll have to take some time to learn the idioms and quirks of another language, but that's fine. Am I really going to be significantly more productive using C# than Java? What about Python? What about Perl or PHP? What about Ruby? Oh, those are boring, eh? Perhaps something like Scala or Lisp would do the trick. Honestly, does it really matter? Sure there are cases where such distinctions do make a difference, but frankly, assuming you've got some kind of reasonable OO language without pointers (I've excluded C and C++ from this discussion), really it comes down to this:&lt;br /&gt;&lt;br /&gt;1) Is the inherent performance adequate for your forseeable needs?&lt;br /&gt;2) Is the platform stable?&lt;br /&gt;3) Can you find suitable libraries for what you want to do without re-inventing the wheel?&lt;br /&gt;4) Have you addressed relevant portability issues?&lt;br /&gt;5) Are the available development environments suitable for your needs/preferences?&lt;br /&gt;&lt;br /&gt;Really, that's about it. Everything else is just kind of annoying dithering. Sure, with real human languages people have a lot of vested interests, plus there are aesthetic concerns. But programming languages have only been around for decades. Do we really need to have a balkanized landscape in the programming language world to mimic that of regular languages in the real world? Apparently so! As for aesthetics, I suppose poetry written in French can never be perfectly translated into English, or Chinese, or Swahili, and so on. But we're talking about computer programs here. The aesthetics should, in my opinion, be limited to expressing things  clearly and economically. Computer programming is much more like technical writing than poetry. If there are real aesthetics to it, then I would say any poetry in programming lives in the realm of algorithms, which are language-agnostic anyway. Then there are the endless debates about changes to programming languages. I had an email discussion recently with a fellow about checked exceptions in Java and how terrible they were. My goodness. If you don't like them, then don't use them. It's easy to dispense with them. It's not a problem. Frankly it's a waste of mental energy to discuss things like this. But that's what people are into these days. Endless onanizing with the latest and coolest language features. Should the language be more dynamic? Less dynamic? Can we write our own specialized Domain Specific Languages? Sigh...&lt;br /&gt;&lt;br /&gt;Finally there's the methodology cesspool. I have my own views. The problem is that this issue tends to be at the forefront all the time. Is XP good? Are all XP practices good? Is agile a religion or a con? What's the difference between agile and lean? The simple reality is having competent and motivated programmers is good. Having unmotivated and incompetent programmers is bad. If you have competent and motivated programmers, then a really bad methodology may cripple them, but nothing short of the insanity of the CMM stuff is likely to do that.&lt;br /&gt;&lt;br /&gt;&lt;a href="http://www.yosefk.com/blog/extreme-programming-explained.html"&gt;&lt;/a&gt;&lt;blockquote&gt;&lt;a href="http://www.yosefk.com/blog/extreme-programming-explained.html"&gt;CMM level 5, denotes complete paralysis.  Levels 2 to 4 indicate various intermediate stages where paralysis is spreading, but you can still ship.&lt;/a&gt;&lt;br /&gt;&lt;/blockquote&gt;The norm is simply chaos without any form at all: The hack and fix grind. Outside the realm of complete insanity, there are practices that most reasonable people would agree on: Automated tests for regression and quality; using a revision control system; integrating the tests into the revision control system as part of an automated build; planning and designing in some kind of iterative fashion; communicating - you know, like, talking to one another in some way that doesn't involve exchanging 200 page documents. Cooperation - people involved genuinely wanting to help one another reach the goal.&lt;br /&gt;&lt;br /&gt;Ok, you get the idea. Beyond that, it's all about refinement. Don't like pair-programming? Fine. Prefer writing automated tests after you write the code for a particular feature? Well, I disagree, but ok, go for it.  Find occasions in which some detailed planning and design is necessary? Hey, do it - just don't lose it and end up in in(s)anity land again.&lt;br /&gt;&lt;br /&gt;What's my point? Well, it's that the real problem with programming is that developers aren't competent enough. There is not enough understanding of core programming ideas - either that or there isn't enough self-discipline to appy them: Reduce duplication; encapsulate; reduce coupling; increase cohesion; emphasize clarity; resist the urge to obfuscate; no matter how tempting it might be, choose the plain way to do something rather than the really fancy: Avoid the way that uses some new fangled language feature unless you can demonstrate the plain way is going to be a serious problem.Whatever you do, avoid falling in love with object-oriented design for its own sake (or functional programming for its own sake).  You should be able to show how everything you do emphasize clarity and reduces duplication and coupling. At the end of the day, a good program written in Python should look almost identical to the same thing written in Java. What are your objects? What are their functions? How have you removed duplication? It's not a sexy problem. Switching to a new programming language or a new methodology won't help. It's just the slow grind of educating people, educating ourselves, and keeping things as simple as possible.&lt;br /&gt;&lt;br /&gt;&lt;br /&gt;Think about it.&lt;div class="blogger-post-footer"&gt;&lt;img width='1' height='1' src='https://blogger.googleusercontent.com/tracker/10784478-1190786892972589415?l=vladimirlevin.blogspot.com' alt='' /&gt;&lt;/div&gt;</content><link rel='replies' type='application/atom+xml' href='http://vladimirlevin.blogspot.com/feeds/1190786892972589415/comments/default' title='Post Comments'/><link rel='replies' type='text/html' href='http://www.blogger.com/comment.g?blogID=10784478&amp;postID=1190786892972589415' title='7 Comments'/><link rel='edit' type='application/atom+xml' href='http://www.blogger.com/feeds/10784478/posts/default/1190786892972589415'/><link rel='self' type='application/atom+xml' href='http://www.blogger.com/feeds/10784478/posts/default/1190786892972589415'/><link rel='alternate' type='text/html' href='http://vladimirlevin.blogspot.com/2008/07/problem-with-popplers.html' title='The Problem With Popplers'/><author><name>Vladimir Levin</name><uri>http://www.blogger.com/profile/09680919094932667147</uri><email>noreply@blogger.com</email><gd:image rel='http://schemas.google.com/g/2005#thumbnail' width='21' height='32' src='http://2.bp.blogspot.com/_zD5Hp0u_Wi0/SqSQJLR_0_I/AAAAAAAAADE/l8j4ET6y63E/S220/vlad_korean.jpg'/></author><thr:total>7</thr:total></entry><entry><id>tag:blogger.com,1999:blog-10784478.post-8031845346111021861</id><published>2008-03-09T20:30:00.003-07:00</published><updated>2008-03-09T21:33:13.944-07:00</updated><title type='text'>Hitting the Reset Button</title><content type='html'>All too often in the software world we convince ourselves to keep going with a design that just wasn't quite right from the start. We're not willing to say, let's scrap this and use what we learned to make it better next time. The result is that the technology becomes increasingly crufty and after a while, it's hard to know where to even start to improve things. I think it's important to have the courage to make tough decisions and rework designs that need it as soon as possible, even if it means rolling up our sleeves to do some hard work and dealing with some short term pain during the transition. I've quoted a piece of an interview that &lt;a href="http://money.cnn.com/galleries/2008/fortune/0803/gallery.jobsqna.fortune/10.html"&gt;CNN&lt;/a&gt; did with Steve Jobs below, but I'd like to first show the key highlight, at least from my point of view:&lt;br /&gt;&lt;blockquote&gt;But there always seems to come a moment where it's just not working, and it's so easy to fool yourself - to convince yourself that it is when you know in your heart that it isn't&lt;br /&gt;&lt;/blockquote&gt;&lt;br /&gt;It really is so easy to fool yourself. I think it's true that the great companies and great teams don't just come out of the gate with winners; rather they have the humility and courage to evaluate their work and start again when they have to.  Anyway, here' s the rest of the part of the interview I wanted to quote:&lt;br /&gt;&lt;blockquote&gt;                                                        At Pixar when we were making &lt;i&gt;Toy Story&lt;/i&gt;, there came a time when we were forced to admit that the story wasn't great. It just wasn't great. We stopped production for five months.... We paid them all to twiddle their thumbs while the team perfected the story into what became &lt;i&gt;Toy Story&lt;/i&gt;. And if they hadn't had the courage to stop, there would have never been a &lt;i&gt;Toy Story&lt;/i&gt; the way it is, and there probably would have never been a Pixar. &lt;p&gt;We called that the 'story crisis,' and we never expected to have another one. But you know what? There's been one on every film. We don't stop production for five months. We've gotten a little smarter about it. But there always seems to come a moment where it's just not working, and it's so easy to fool yourself - to convince yourself that it is when you know in your heart that it isn't. &lt;/p&gt;&lt;p&gt;Well, you know what? It's been that way with [almost] every major project at Apple, too.... Take the iPhone. We had a different enclosure design for this iPhone until way too close to the introduction to ever change it. And I came in one Monday morning, I said, 'I just don't love this. I can't convince myself to fall in love with this. And this is the most important product we've ever done.' &lt;/p&gt;&lt;p&gt;And we pushed the reset button. We went through all of the zillions of models we'd made and ideas we'd had. And we ended up creating what you see here as the iPhone, which is dramatically better. It was hell because we had to go to the team and say, 'All this work you've [done] for the last year, we're going to have to throw it away and start over, and we're going to have to work twice as hard now because we don't have enough time.' And you know what everybody said? 'Sign us up.' &lt;/p&gt;&lt;p&gt;That happens more than you think, because this is not just engineering and science. There is art, too. Sometimes when you're in the middle of one of these crises, you're not sure you're going to make it to the other end. But we've always made it, and so we have a certain degree of confidence, although sometimes you wonder. I think the key thing is that we're not all terrified at the same time. I mean, we do put our heart and soul into these things.&lt;br /&gt;&lt;/p&gt;&lt;/blockquote&gt;&lt;div class="blogger-post-footer"&gt;&lt;img width='1' height='1' src='https://blogger.googleusercontent.com/tracker/10784478-8031845346111021861?l=vladimirlevin.blogspot.com' alt='' /&gt;&lt;/div&gt;</content><link rel='replies' type='application/atom+xml' href='http://vladimirlevin.blogspot.com/feeds/8031845346111021861/comments/default' title='Post Comments'/><link rel='replies' type='text/html' href='http://www.blogger.com/comment.g?blogID=10784478&amp;postID=8031845346111021861' title='0 Comments'/><link rel='edit' type='application/atom+xml' href='http://www.blogger.com/feeds/10784478/posts/default/8031845346111021861'/><link rel='self' type='application/atom+xml' href='http://www.blogger.com/feeds/10784478/posts/default/8031845346111021861'/><link rel='alternate' type='text/html' href='http://vladimirlevin.blogspot.com/2008/03/hitting-reset-button_09.html' title='Hitting the Reset Button'/><author><name>Vladimir Levin</name><uri>http://www.blogger.com/profile/09680919094932667147</uri><email>noreply@blogger.com</email><gd:image rel='http://schemas.google.com/g/2005#thumbnail' width='21' height='32' src='http://2.bp.blogspot.com/_zD5Hp0u_Wi0/SqSQJLR_0_I/AAAAAAAAADE/l8j4ET6y63E/S220/vlad_korean.jpg'/></author><thr:total>0</thr:total></entry><entry><id>tag:blogger.com,1999:blog-10784478.post-6700625410947121884</id><published>2007-11-24T13:44:00.000-08:00</published><updated>2007-11-25T00:19:25.699-08:00</updated><title type='text'>Pair Programming Redux</title><content type='html'>I've been working for a few years in a mostly XP pair programming environment. Here's my list of pros and cons of pair programming based on this experience:&lt;br /&gt;&lt;br /&gt;Pros:&lt;br /&gt;&lt;ul&gt;&lt;li&gt;Unlike most other projects I've worked on, I've seen an overall &lt;span style="font-style: italic;"&gt;improvement &lt;/span&gt;in the code quality over the past few years. I've never seen that happen on any other project. As people learn better ways of doing things, pairing helps to disseminate that knowledge in a way that meetings, presentations, and code reviews just don't.&lt;br /&gt;&lt;/li&gt;&lt;li&gt;In my experience, there hasn't been a problem with people who are working together arguing and consequently getting nothing done. On the contrary, pairing seems to have encouraged an atmosphere of cooperation and friendliness.&lt;/li&gt;&lt;li&gt;Sometimes under time pressure one can't resist the urge to copy and paste some code or hack in some functionality without developing tests first. The mutual supervision of pair programming really does seem to have a positive effect on these kinds of transgressions. It's a lot harder to take a nasty shortcut under the watchful eye of the person you're pairing with.&lt;br /&gt;&lt;/li&gt;&lt;li&gt;I would tend to agree with the principle that working in pairs doesn't really hurt overall productivity. The reason seems to be that the team having a common understanding of the code and the business generally trumps the value of having two people typing code in separately. Integration is the real difficulty in many software projects, so whatever gain in the amount of code written might come from separating pairs, that gain seems to be offset by the greater consistency of code written when pairing.&lt;br /&gt;&lt;/li&gt;&lt;/ul&gt;Cons:&lt;br /&gt;&lt;ul&gt;&lt;li&gt;Hygiene: Pair programming in our environment means sharing one keyboard and mouse, and sitting in close proximity to another person all day long as well as switching pairs frequently. We often have had problems with people spreading colds around the office. I think developers in an XP shop should have their own personal wireless mouse/keyboard combination as well as their own chair that they don't have to share with anyone else.&lt;br /&gt;&lt;/li&gt;&lt;li&gt;Ergonomics: As someone who suffers from pain problems, I am especially sensitive to ergonomics. The reality is that sitting at a computer is not a natural position for the body and you can do damage to your back, neck, shoulders and head, and of course your wrists over time. Pairing tends to encourage bad ergonomic habits, because it's inconvenient to change the position of the keyboard tray, monitor, chair, etc when it's time to take one's turn at the keyboard. I really believe that these things need to be considered if you want to do pair programming long term.&lt;/li&gt;&lt;li&gt;Personal space: Some people enjoy having some peace and quiet as well as a space where they can keep their things. As much as I am a fan of pair programming, I think developers should have their own desks away from the common bull pen they can retreat to from time to time.&lt;/li&gt;&lt;/ul&gt;My conclusion is that pair programming does work, but it requires some care. First, developers have to respect each other and be willing to compromise. Also, pair programming 100% of the time doesn't work. Sometimes when facing a design problem it helps to go off and work separately, then get back together and discuss later. Also, pair programming - constantly communicating, asking questions, explaining and justifying one's own ideas throughout the day - is very demanding.  After a period of time, burnout can occur. When that happens, I think it's a good idea for people to be able to work on something alone for a while.&lt;div class="blogger-post-footer"&gt;&lt;img width='1' height='1' src='https://blogger.googleusercontent.com/tracker/10784478-6700625410947121884?l=vladimirlevin.blogspot.com' alt='' /&gt;&lt;/div&gt;</content><link rel='replies' type='application/atom+xml' href='http://vladimirlevin.blogspot.com/feeds/6700625410947121884/comments/default' title='Post Comments'/><link rel='replies' type='text/html' href='http://www.blogger.com/comment.g?blogID=10784478&amp;postID=6700625410947121884' title='6 Comments'/><link rel='edit' type='application/atom+xml' href='http://www.blogger.com/feeds/10784478/posts/default/6700625410947121884'/><link rel='self' type='application/atom+xml' href='http://www.blogger.com/feeds/10784478/posts/default/6700625410947121884'/><link rel='alternate' type='text/html' href='http://vladimirlevin.blogspot.com/2007/11/pair-programming.html' title='Pair Programming Redux'/><author><name>Vladimir Levin</name><uri>http://www.blogger.com/profile/09680919094932667147</uri><email>noreply@blogger.com</email><gd:image rel='http://schemas.google.com/g/2005#thumbnail' width='21' height='32' src='http://2.bp.blogspot.com/_zD5Hp0u_Wi0/SqSQJLR_0_I/AAAAAAAAADE/l8j4ET6y63E/S220/vlad_korean.jpg'/></author><thr:total>6</thr:total></entry><entry><id>tag:blogger.com,1999:blog-10784478.post-3042391580491736074</id><published>2007-11-15T17:08:00.000-08:00</published><updated>2008-05-16T09:19:04.498-07:00</updated><title type='text'>Demystefying Stubs, Fakes, and Mock Objects</title><content type='html'>This blog entry is my attempt to explain the different kinds test-only objects that can be substituted for the real thing in automated tests: Stubs, Fakes, and Mocks. It can be easy to get confused, so I hope this entry helps!&lt;br /&gt;&lt;br /&gt;Stubs, fakes, and mocks are all objects that replace the objects that would normally be used in the actual application. What purpose do they serve? First, using such test-only objects promotes good design. Writing code so that classes have dependencies on interfaces and abstract classes which can be  implemented either by the full-fledged production code or by a test-only class of some kind helps to reduce the overall &lt;a href="http://en.wikipedia.org/wiki/Loose_coupling"&gt;coupling &lt;/a&gt;in an application.  Test-only objects frequently come up when an application is accessing another system:  Making sure that system is available and produces the same response to a given input all the time may be a problem (consider a service that provides the current price for stocks for example).  Also, simply configuring something like a relational database or a web server so that tests can run against it can be an issue. More generally, using a test-only object makes it easier to set up the initial conditions for  tests. Such objects can make it simpler to provide the initial state that the function under test will respond to. The time it takes for tests to run can also be an factor; using simple test-only objects can speed up the time it takes for tests to run substantially. Finally, in some cases one may want to develop some logic that depends on classes that haven't been written yet or that you don't have access to. Say for example another team is working on that functionality and you don't have access to their code. In such cases, you can write code against objects that, for the purposes of testing your own logic,  implement the interfaces you expect to see in the yet-to-be-written API. The core idea behind the use of test-only objects is that we often want to write tests for the application logic we're currently working on without having to worry about th behaviour of some of the external code our logic is using.&lt;br /&gt;&lt;br /&gt;Let's consider an example. I once wrote a program that allowed a user to schedule polling of different sensors - e.g. read sensor 'A' once an hour, sensor 'B' every minute, and sensor 'C' every second. I wanted to test my scheduling logic, but I wanted to make it independent from the actual sensors:  I didn't want to have my application connected to real sensors just to make the my unit tests run. Also the scheduling system of course obtained the computer's system time to see whether it was time to read a given sensor. I also wanted my tests to be independent of the actual system time: What I wanted was to set the time in my test and make sure my program responded by reading the correct sensors - and avoided reading the wrong ones. I didn't want to have to set the actual computer's system time inside of my tests! So, for both of these cases, the business of actually connecting to the sensors and setting and reading the time, I created special test-only objects to stand-in for the ones that would be used in the actual application.&lt;br /&gt;&lt;br /&gt;If you're interested in ways to instrument your code, and the trade-offs involved, so that you can substitute these kinds of test-only objects &lt;a href="http://langrsoft.com/"&gt;Jeff Langr's&lt;/a&gt; &lt;a href="http://langrsoft.com/articles/mocking.shtml"&gt;Don't Mock Me&lt;/a&gt; article is a great reference. I should note that his use of the word "mock" is more generic than the one that's often used. He means "mock" in the general sense of any kind of test object. As we'll see a bit further down, mock objects often have a specific meaning that's different from stubs and fakes.&lt;br /&gt;&lt;br /&gt;Now, on to Stubs, Fakes, and Mocks.&lt;br /&gt;&lt;br /&gt;&lt;span style="font-weight: bold;"&gt;Stub:&lt;/span&gt; A stub is an object that always does the same thing. It's very simple and very dumb. In our example above of polling sensors, the system time seems like a useful entity to replace with a stub.  Let's suppose our scheduling code was in a class called Scheduler. This class might have a method called getSystemTime(). For the purpose of testing, we might create a TestingScheduler class that extends Scheduler and overrides the getSystemTime() method. Now you can set the system time in the constructor of this test-specific class, e.g:&lt;br /&gt;&lt;pre&gt;&lt;br /&gt;public class TestingScheduler extends Scheduler {&lt;br /&gt;public TestingScheduler(int timeInMillisForTest) {&lt;br /&gt;this.timeInMillisForTest = timeInMillisForTest;&lt;br /&gt;}&lt;br /&gt;&lt;br /&gt;public int getSystemTime() {&lt;br /&gt;return timeInMillisForTest;&lt;br /&gt;}&lt;br /&gt;}&lt;br /&gt;&lt;/pre&gt;&lt;br /&gt;When a TestingShcheduler object is used as part of a test, the rest of the Scheduler logic works normally, but it's now getting the time that's been set in the test instead of the actual system time.&lt;br /&gt;&lt;br /&gt;&lt;span style="font-weight: bold;"&gt;Fake:&lt;/span&gt;  A fake is a more sophisticated kind of test object. The idea is that the object actually displays some real behaviour, yet in some essential ways it is not the real thing. Fakes can be used to speed up the time it takes tests to run and/or to simplify configuration. For example, a project I am currently working on is using Oracle's &lt;a href="http://www.oracle.com/technology/products/ias/toplink/index.html"&gt;Toplink&lt;/a&gt; as an object-relational mapper (ORM). This allows data in Java objects to be transparently saved to and retrieved from a relational database. To make tests that use this framework run faster, a much simplified memory-only implementation of Toplink's interfaces was implemented. This version doesn't know about transactions and doesn't actually persist data, but it works well enough to allow many of our tests to run against it - and since the actual Oracle database isn't involved, the tests run over an order of magnitude faster. Going back to the scheduler example, we developed a piece of software that could behave as though it was a real sensor. That way we were able to run a variety of fairly complicated tests to make sure our application could communicate with sensors correctly without actually having to hook up the tests to a real sensor. Any time you write code that simulates an external service - some sensors, a Web server, or what have you, you're creating a fake.&lt;br /&gt;&lt;br /&gt;You can find a simple example of  a fake in the &lt;a href="http://www.geocities.com/vladimir_levin/loop_finder.html#test_node"&gt;TestNode&lt;/a&gt; class in my &lt;a href="http://www.geocities.com/vladimir_levin/loop_finder.html"&gt;loop finder&lt;/a&gt; example. The TestNode implements the Node interface for the purposes of the unit tests. Classes that are actually part of the application have their own, more complex implementation, of this interface  - but we're not interested in testing their implementation of the Node interface here. This allows us to write tests that can run in isolation from the rest of the application. From the perspective of the overall design, this approach helps us to reduce coupling between classes. The LoopFinder class only depends on the Node interface rather than on any specific implementation. That's an example of how making code easier to test concomitantly improves the design.&lt;br /&gt;&lt;br /&gt;&lt;span style="font-weight: bold;"&gt;Mock: &lt;/span&gt;Mock objects can be the most confusing to understand. First of all, one can argue that the two types of test classes mentioned above are mocks. After all, they both "mock out" or "simulate" a real class. In fact mocks are a certain kind of stub or fake. However, the additional  feature mock objects offer on top of acting as simple stubs or fakes is that they provide a flexible way to specify more directly how your function under test should actually operate. In this sense they also act as a kind of recording device: They keep track of which of the mock object's methods are called, with what kind of parameters, and how many times. If your function under test fails to exercise the mock as specified in the test, the test fails. That's why developing using mock objects is often called "interaction testing." You're not only writing a test which confirms that state after a given method call matches the expected values; you're also specifying how the objects in the function under test, which of course have been replaced with mocks, ought be exercised within a given test.&lt;br /&gt;&lt;br /&gt;To sum up: A mock object framework can make sure a) that the method under test, when executed, will in fact call certain functions on the mock object (or objects) it interacts with and b) that the method under test will react in an appropriate way to whatever the mock objects do - this second part is not any different from what stubs and fakes offer.&lt;br /&gt;&lt;br /&gt;We've already seen how stubs and fakes can be used, so let's create a hand-rolled example of the kind of thing that mock object frameworks can help with. Let's go back to the scheduler we've already talked about. Let's say the scheduler processes a queue of ScheduledItem objects (ScheduledItem might be an interface) . If it's time to run one of these items, the scheduler calls the item's execute method. In our test, we can create a queue of mock items such that only one of them is supposed to be executed.  A simple way of implementing this mock item might look something like this:&lt;br /&gt;&lt;pre&gt;&lt;br /&gt;public interface ScheduledItem {&lt;br /&gt;public void execute();&lt;br /&gt;public int getNextExecutionTime();&lt;br /&gt;}&lt;br /&gt;&lt;br /&gt;public class MockScheduledItem implements ScheduledItem {&lt;br /&gt;private boolean wasExecuted;&lt;br /&gt;private int nextRun;&lt;br /&gt;&lt;br /&gt;public MockScheduledItem(int nextRun) {&lt;br /&gt;this.nextRun = nextRun;&lt;br /&gt;}&lt;br /&gt;&lt;br /&gt;public  void execute() {&lt;br /&gt;wasExecuted = true;&lt;br /&gt;}&lt;br /&gt;&lt;br /&gt;public int getNextExecutionTime() {&lt;br /&gt;return nextRun;&lt;br /&gt;}&lt;br /&gt;&lt;br /&gt;public boolean getWasExecuted() {&lt;br /&gt;return wasExecuted;&lt;br /&gt;}&lt;br /&gt;}&lt;br /&gt;&lt;/pre&gt;&lt;br /&gt;Our test might look something like this:&lt;br /&gt;&lt;pre&gt;public void testScheduler_MakeSureTheRightItemIsExecuted() {&lt;br /&gt;//setup&lt;br /&gt;MockScheduledItem shouldRun = new MockScheduledItem(1000)&lt;br /&gt;MockScheduledItem shouldNotRun = new MockScheduledItem(2000)&lt;br /&gt;Scheduler scheduler = new TestingScheduler(1100);&lt;br /&gt;scheduler.add(shouldNotRun);&lt;br /&gt;sheduler.add(shouldRun);&lt;br /&gt;&lt;br /&gt;//execute&lt;br /&gt;scheduler.processQueue();&lt;br /&gt;&lt;br /&gt;//verify&lt;br /&gt;assertTrue(shouldRun.getWasExecuted());&lt;br /&gt;assertFalse(shouldNotRun.getWasExecuted());&lt;br /&gt;}&lt;br /&gt;&lt;/pre&gt;That's a really simple, hand-rolled, example of a mock object. The test just makes sure that the processQueue method ran the execute method on the first item, but not for the second one. Of course this example is very simple. We could make it a little fancier by counting the number of times the execute method is called and make sure it's only called once during the test. Then we could start to implement functionality that makes sure functions belonging to a given mock object are called with particular arguments, in a particular order, etc.  Mock object frameworks support this kind of functionality out of the box. You can take any class in your application and create a mock version of that class to be used as part of a test.  There are a bunch of mocking frameworks for many different programming languages.&lt;br /&gt;&lt;br /&gt;Before you dive in, consider my word of caution: In the great spectrum between pure &lt;a href="http://en.wikipedia.org/wiki/Black_box_testing"&gt;black-box&lt;/a&gt; and pure &lt;a href="http://en.wikipedia.org/wiki/White_box_testing"&gt;white-box&lt;/a&gt; testing, using mock objects is about as "white-box" as it gets. You're saying things along the lines of "I want to make sure that when I call function X on object A (the function and object under test), that functions Y on object B and function Z on object C will be called in that order,  with certain specific arguments." When the test you write is making sure that something *happened* as a result of your test, it tends to be easier to understand what the test is trying to do. On the other hand, if your test is just making sure that some functions were called, what does that really mean? Potentially very little.  Also, because your mock objects are basically fakes or stubs, you are not guaranteed that the behaviour of the actual objects that are being mocked out will be consistent with the mocks. In other words, you can create a mock version of an object that adds one to its argument whereas the real function subtracts one. If you change the behaviour of a given function that is being mocked in a test somewhere, you have to be careful to make sure to adjust the mock accordingly. If you don't, you'll wind up with passing tests, but you may still have introduced a bug into the application. This kind of problem tends to become more likely as the sophistication of the fake implementation increases - and pure fakes also suffer from the same weakness. I do think that creating mock tests where the specified interactions become complicated and the mock itself is a sophisticated fake that can respond to a wide variety of interactions compounds the likeliness of running into this kind of problem. Also, on a more basic level, simply refactoring code can be difficult with mock objects. The mock frameworks sometimes use strings to represent the mock object's methods internally, so renaming a method using a refactoring tool may not actually update the mock, and your tests would suddenly fail just because you renamed a function. Of course even a slightly more complicated refactoring, like breaking up a method into two can also cause mock objects to fail trivially, telling you that yes indeed, you actually changed some code.&lt;br /&gt;&lt;br /&gt;As you can tell, I am not a huge fan of extensive use of mock objects in the sense of specifying interactions. I believe that such objects can indeed be useful in specific cases, but that's not how I think about writing my code. When I write a test, I try to keep it simple and concentrate on what I can expect to happen as a result of running that test, not specifically what the execution path of the function under test will look like.  There are of course cases where this type of interaction testing is useful. I think the scheduler example above is a good case in point. You want your test to make sure a method is called, but thats it; you're not interested in what the real implementation of that method may do. All in all, I tend to prefer to stick with simple hand-rolled stubs, fakes, and mocks in my TDD practice. Your mileage may vary. Martin Fowler has &lt;a href="http://martinfowler.com/articles/mocksArentStubs.html"&gt;written about the distinction betwen mocks and stubs/fakes also&lt;/a&gt;.&lt;br /&gt;&lt;br /&gt;I know that when I first encountered "mock objects", I had some trouble figuring out exactly what it meant and what all the fuss was about. If you've found this blog entry because you were experiencing the same confusion, I hope it's been of some help.&lt;br /&gt;&lt;br /&gt;Additional Links:&lt;br /&gt;&lt;ul&gt;&lt;li&gt;&lt;a href="http://en.wikipedia.org/wiki/Mock_object"&gt;Mock objects at Wikipedia&lt;/a&gt;&lt;/li&gt;&lt;li&gt;&lt;a href="http://www.c2.com/cgi/wiki?MockObject"&gt;Mock objects at c2&lt;/a&gt;&lt;/li&gt;&lt;li&gt;&lt;a href="http://xunitpatterns.com/Test%20Double.html"&gt;Test doubles at xUnit Patterns&lt;/a&gt;&lt;br /&gt;&lt;/li&gt;&lt;li&gt;&lt;a href="http://martinfowler.com/articles/mocksArentStubs.html"&gt;Mocks aren't stubs&lt;/a&gt;&lt;/li&gt;&lt;li&gt;&lt;a href="http://langrsoft.com/articles/mocking.shtml"&gt;Don't mock me&lt;/a&gt;&lt;/li&gt;&lt;li&gt;&lt;a href="http://en.wikipedia.org/wiki/Behavior_driven_development"&gt;Behaviour-Driven Development (BDD)&lt;/a&gt;&lt;br /&gt;&lt;/li&gt;&lt;/ul&gt;&lt;div class="blogger-post-footer"&gt;&lt;img width='1' height='1' src='https://blogger.googleusercontent.com/tracker/10784478-3042391580491736074?l=vladimirlevin.blogspot.com' alt='' /&gt;&lt;/div&gt;</content><link rel='replies' type='application/atom+xml' href='http://vladimirlevin.blogspot.com/feeds/3042391580491736074/comments/default' title='Post Comments'/><link rel='replies' type='text/html' href='http://www.blogger.com/comment.g?blogID=10784478&amp;postID=3042391580491736074' title='9 Comments'/><link rel='edit' type='application/atom+xml' href='http://www.blogger.com/feeds/10784478/posts/default/3042391580491736074'/><link rel='self' type='application/atom+xml' href='http://www.blogger.com/feeds/10784478/posts/default/3042391580491736074'/><link rel='alternate' type='text/html' href='http://vladimirlevin.blogspot.com/2007/11/stubs-fakes-mocks.html' title='Demystefying Stubs, Fakes, and Mock Objects'/><author><name>Vladimir Levin</name><uri>http://www.blogger.com/profile/09680919094932667147</uri><email>noreply@blogger.com</email><gd:image rel='http://schemas.google.com/g/2005#thumbnail' width='21' height='32' src='http://2.bp.blogspot.com/_zD5Hp0u_Wi0/SqSQJLR_0_I/AAAAAAAAADE/l8j4ET6y63E/S220/vlad_korean.jpg'/></author><thr:total>9</thr:total></entry><entry><id>tag:blogger.com,1999:blog-10784478.post-9169042964161113568</id><published>2007-11-12T01:00:00.001-08:00</published><updated>2007-11-12T18:02:37.766-08:00</updated><title type='text'>Even Grandmasters Get The Blues</title><content type='html'>I read an article some months ago about &lt;a href="http://www.chessbase.com/newsdetail.asp?newsid=3509"&gt;Vladimir Kramnik's incredible mistake in a game against the computer opponent Deep Fritz&lt;/a&gt;. Kramnik was at that point the undisputed world champion in chess - apparently the first person to achieve that status since Kasparov. In this game however, he made a truly astounding blunder. Deep Fritz had made a move that threatened an immediate check mate. Even someone like me who barely knows the rules of chess can see this fairly easily, but somehow Kramnik missed it. Here's a diagram of what happened:&lt;br /&gt;&lt;br /&gt;&lt;a onblur="try {parent.deselectBloggerImageGracefully();} catch(e) {}" href="http://1.bp.blogspot.com/_zD5Hp0u_Wi0/Rzja9lIwoqI/AAAAAAAAACA/yUDuWmXwXEs/s1600-h/chess.JPG"&gt;&lt;img style="cursor: pointer;" src="http://1.bp.blogspot.com/_zD5Hp0u_Wi0/Rzja9lIwoqI/AAAAAAAAACA/yUDuWmXwXEs/s320/chess.JPG" alt="" id="BLOGGER_PHOTO_ID_5132092526864409250" border="0" /&gt;&lt;/a&gt;&lt;br /&gt;&lt;br /&gt;With Deep Fritz's queen at E4 threatening to check mate at H7 with the very next move, Kramnik, instead of defending, blithely moved his queen from A7 to E3. In an instant, the game was over. Here is an account of the events:&lt;br /&gt;&lt;br /&gt;&lt;blockquote&gt;Kramnik played the move 34...Qe3 calmly, stood up, picked up his cup and was    about to leave the stage to go to his rest room. At least one audio commentator    also noticed nothing, while Fritz operator Mathias Feist kept glancing from    the board to the screen and back, hardly able to believe that he had input the    correct move. Fritz was displaying mate in one, and when Mathias executed it    on the board Kramnik briefly grasped his forehead, took a seat to sign the score    sheet and left for the press conference, which he dutifully attended.&lt;br /&gt;&lt;/blockquote&gt;&lt;br /&gt;It's a fascinating thing. How could Kramnik have made such an error? There could be lots of explanations. He might have been ill or in a bad mood. He might have been experiencing a lot of stress because his opponent was a computer: It must be psychologically difficult to cope with the idea of an opponent with perfect memory who will never make a reading mistake or get tired; an opponent who can not be intimidated with an agressive move, or confused, or tricked. Never the less, the fact is that this mistake really did happen.&lt;br /&gt;&lt;br /&gt;For me this might be an interesting example of a phenomenon I'll call the "expert's blunder," which can apply to anything, and in particular, to software development. A beginner in any field has a very small number of things he or she can keep track of. As one learns more and more about a given area however, one has to think of an ever expanding tree of concepts and ideas. Anything you do as an expert is heavier and more difficult. The more you know, the more tools are available to you, the more effort is required to choose which tool or approach to use next. It becomes easier to overlook something completely simple that a beginner would spot right away. As Kramnik was playing this ill-fated game, I think he wasn't really looking at the current state of the board, but rather at his own mental picture, a cloud of variations and possibilities. He might have got out of sync with his place in the actual game.&lt;br /&gt;&lt;br /&gt;I've noticed this kind of thing happening to me when I've found myself implementing a more complicated piece of code than was necessary. Here's a case I blogged about some time ago for example: &lt;a href="http://vladimirlevin.blogspot.com/2006/05/mixins-interfaces-and-multiple.html"&gt;My original blog entry&lt;/a&gt;, followed by &lt;a href="http://vladimirlevin.blogspot.com/2006/06/further-lessons-in-humility.html"&gt;my realization that my code was over-designed&lt;/a&gt;. Here I too was getting ahead of myself, thinking of classes and subclasses and interfaces instead of just solving the problem in the most straightforward way. I think this kind of mistake is a good example of why TDD (test-driven development) and pair programming are useful tools in software development. The more we focus on the simple step-by-step design process of TDD and the more we constantly subject our code to critique as we do in pair programming, the less likely we are to develop bloated and over-designed code - however well-intentioned we might have been in writing it in the first place. I think this also promotes the idea of pairing a seasoned veteran with a recent grad: The value flows in both directions, not just from the expert to the novice. Not only beginners can write bad code. By virtue of their experience, people with more knowledge can be just as susceptible. At the very least, it's safe to say that one should always pause and just "look at the board" every so often.&lt;div class="blogger-post-footer"&gt;&lt;img width='1' height='1' src='https://blogger.googleusercontent.com/tracker/10784478-9169042964161113568?l=vladimirlevin.blogspot.com' alt='' /&gt;&lt;/div&gt;</content><link rel='replies' type='application/atom+xml' href='http://vladimirlevin.blogspot.com/feeds/9169042964161113568/comments/default' title='Post Comments'/><link rel='replies' type='text/html' href='http://www.blogger.com/comment.g?blogID=10784478&amp;postID=9169042964161113568' title='0 Comments'/><link rel='edit' type='application/atom+xml' href='http://www.blogger.com/feeds/10784478/posts/default/9169042964161113568'/><link rel='self' type='application/atom+xml' href='http://www.blogger.com/feeds/10784478/posts/default/9169042964161113568'/><link rel='alternate' type='text/html' href='http://vladimirlevin.blogspot.com/2007/11/even-grandmasters-get-blues.html' title='Even Grandmasters Get The Blues'/><author><name>Vladimir Levin</name><uri>http://www.blogger.com/profile/09680919094932667147</uri><email>noreply@blogger.com</email><gd:image rel='http://schemas.google.com/g/2005#thumbnail' width='21' height='32' src='http://2.bp.blogspot.com/_zD5Hp0u_Wi0/SqSQJLR_0_I/AAAAAAAAADE/l8j4ET6y63E/S220/vlad_korean.jpg'/></author><media:thumbnail xmlns:media='http://search.yahoo.com/mrss/' url='http://1.bp.blogspot.com/_zD5Hp0u_Wi0/Rzja9lIwoqI/AAAAAAAAACA/yUDuWmXwXEs/s72-c/chess.JPG' height='72' width='72'/><thr:total>0</thr:total></entry><entry><id>tag:blogger.com,1999:blog-10784478.post-3057848646574056316</id><published>2007-11-10T21:02:00.000-08:00</published><updated>2007-11-12T14:43:35.184-08:00</updated><title type='text'>Fun Introductory Software Projects</title><content type='html'>I've taught some evening/weekend courses in software development over the years. Usually I've taught adults, but sometimes I've had the chance to work with some talented kids too - from about 12 to 17 years of age. I have to admit, working with the kids was great. Someone recently suggested that I write up some of the projects that were done during these courses. I've always had students come up with their own ideas: I'm a big believer that if you come up with your own idea for something to work on, you'll be genuinely motivated. Therefore, I really suggest coming up with your own concept if you're looking for a project to work on... In case you're looking for some inspiration though, here are some of the types of things people in my courses have done. Have fun!&lt;br /&gt;&lt;br /&gt;&lt;ul&gt;&lt;li&gt;A version of the famous &lt;a href="http://en.wikipedia.org/wiki/Snake_%28video_game%29"&gt;"snake"&lt;/a&gt; video game.&lt;/li&gt;&lt;li&gt;A really neat &lt;span style="font-style: italic;"&gt;original &lt;/span&gt;80's style arcade game which involved shooting a mothership and picking up space junk floating around on the screen to augment one's own spaceship. Let me tell you, it's quite an experience asking about how the swarming bullets were done and getting the reply "Oh, it's a very simple algorithm, but the swarming is emergent behaviour" from a 13/14 year old.&lt;/li&gt;&lt;li&gt;A simple contact manager which you can enter people's information and pictures into. This program used a file to store its data, so all of the storage/retrieval routines had to be written from scratch as opposed to using a database program, which proved quite instructive to the developer.&lt;/li&gt;&lt;li&gt;A very impressive network multi-player   game along the lines of Warcraft (albeit much simpler). The programmer did good work with path-finding and making sure all players were in sync. The players were happy faces of different colors which became sad faces as you attacked them.&lt;/li&gt;&lt;li&gt;An online pizza-ordering application. I recall some good discussions about the user interface and whether it was ok to allow people to order who didn't want to enter in their credit-card information.&lt;/li&gt;&lt;li&gt;A chat program along the lines of ICQ/Instant Messenger&lt;/li&gt;&lt;li&gt;A "&lt;a href="http://en.wikipedia.org/wiki/Tower_of_Hanoi"&gt;Towers of Hanoi&lt;/a&gt;" program in which the user could select the number of disks.  The user could play the game him/herself or let the computer solve the puzzle. A  challenging bonus (which in this case was not implemented) would be to incorporate a "hint for next move" feature.&lt;/li&gt;&lt;/ul&gt;&lt;div class="blogger-post-footer"&gt;&lt;img width='1' height='1' src='https://blogger.googleusercontent.com/tracker/10784478-3057848646574056316?l=vladimirlevin.blogspot.com' alt='' /&gt;&lt;/div&gt;</content><link rel='replies' type='application/atom+xml' href='http://vladimirlevin.blogspot.com/feeds/3057848646574056316/comments/default' title='Post Comments'/><link rel='replies' type='text/html' href='http://www.blogger.com/comment.g?blogID=10784478&amp;postID=3057848646574056316' title='0 Comments'/><link rel='edit' type='application/atom+xml' href='http://www.blogger.com/feeds/10784478/posts/default/3057848646574056316'/><link rel='self' type='application/atom+xml' href='http://www.blogger.com/feeds/10784478/posts/default/3057848646574056316'/><link rel='alternate' type='text/html' href='http://vladimirlevin.blogspot.com/2007/11/fun-introductory-software-projects.html' title='Fun Introductory Software Projects'/><author><name>Vladimir Levin</name><uri>http://www.blogger.com/profile/09680919094932667147</uri><email>noreply@blogger.com</email><gd:image rel='http://schemas.google.com/g/2005#thumbnail' width='21' height='32' src='http://2.bp.blogspot.com/_zD5Hp0u_Wi0/SqSQJLR_0_I/AAAAAAAAADE/l8j4ET6y63E/S220/vlad_korean.jpg'/></author><thr:total>0</thr:total></entry><entry><id>tag:blogger.com,1999:blog-10784478.post-7953938800697990896</id><published>2007-10-08T18:58:00.001-07:00</published><updated>2007-10-08T20:01:33.127-07:00</updated><title type='text'>Estimating Software Development</title><content type='html'>This blog entry was prompted by some thoughts I wanted to express about what it meant to make estimates for software projects in an agile way, and also by Steve Mcconnell's recent blog about &lt;a href="http://blogs.construx.com/blogs/stevemcc/archive/2007/09/23/building-a-fort-lessons-in-software-estimation.aspx"&gt;Building a Fort&lt;/a&gt;.&lt;br /&gt;&lt;br /&gt;The traditional way of estimating software development uses what I'd call a bottom-up approach. You discuss the requirements for the project in great detail with the customer, breaking the project into small pieces. You then estimate how long each of the pieces will take to develop, and then you add everything up to get the estimate for the entire project. In general, I don't think this is really a good idea for software projects. First of all, requirements really do change as time goes on, and an up-front estimate doesn't take that into account. Second of all, communication about requirements using words is a tricky business. I've witnessed, and engaged in, so many discussions where people seemed to agree when in fact they had very different visions. The converse is also often the case: It seems as if people completely disagree, and keep arguing about various points, when in fact they actually have a lot in common. They just don't realize it. So communication is really tough, especially when it comes to software projects where there is always so much room for interpretation. It's very likely that the breakdown of requirements won't be as accurate as it may seem at first. Finally, estimating the amount of time needed for a whole bunch of small requirements without having actually done any real work yet is dangerous too. Will something take two hours, two days, or two weeks? It's hard to say, but it's easy to give something a value and then to assume that it must be accurate. After all, the process to get that value was time consuming and very detailed!&lt;br /&gt;&lt;br /&gt;In agile software development we try to be more realistic. I see it as as combining a top-down approach with a less detailed bottom-up strategy.  The top-down way of estimating is simple. Try to compare apples with apples. If you (or your company) are asked to develop something, base the estimate on a similar project you've done fairly recently with comparable technology. That will give you a wonderful first-order estimate without breaking down the requirements at all. Next comes the agile version of bottom-up estimating. This involves breaking requirements down into a list that the customer prioritizes. For a smaller project, these chunks may be about a week's worth of work - the maximum size of most &lt;a href="http://c2.com/cgi/wiki?UserStory"&gt;XP stories&lt;/a&gt;. For larger projects, they each might be about a month of work - the size of a &lt;a href="http://c2.com/cgi/wiki?ScrumSprint"&gt;Scrum sprint&lt;/a&gt;. The point is to provide an estimate that is based more on the sense of the scope and difficulty of each broad set of requirements without analyzing them to death. Once you've estimated each of the items on this prioritized list - it's called the &lt;a href="http://c2.com/cgi/wiki?ProductBacklog"&gt;Product Backlog&lt;/a&gt; in &lt;a href="http://c2.com/cgi/wiki?ScrumProcess"&gt;Scrum &lt;/a&gt;- you can compare the total estimate you arrive at with the earlier estimate using the top-down approach. Combining these two techniques should produce the kind of estimate that can be used to bid on or evaluate whether to go ahead with a project.&lt;br /&gt;&lt;br /&gt;The important thing is that after each month-long iteration, or even earlier depending on the size of the project, you'll be able to compare the original estimate with the actual development time. After the first month, would the customer agree that you've completed what they expected to see? If you fall short, how much more time does it wind up taking for the the customers to say, 'yes, this is what we thought we would see for the first iteration'? That ratio is called the velocity. Say you took 25 days to complete what was estimated to take 20 days. That means your velocity is 20/25 = 0.8, or 80%. You can use the information to plan the next iteration, and so on as the project goes ahead.&lt;br /&gt;&lt;br /&gt;There are a couple of nice things about this way of doing things. The first one is that you don't have to argue so much with the customer about what a requirement means. Say you estimated 20 days for feature X. After 20 days you present your software to the client. The client says, 'no, this isn't complete. You missed this and that'. I've seen my fair share of projects go completely off the rails when arguments like that break out, but with this agile approach, it doesn't matter so much. You discuss the missing pieces with the customer. Let's say, using our earlier numbers, that you take an additional 5 days to get everything done in a way the customer is happy with. That means, in a certain sense, that your velocity of 80% represents the difference between your original understanding of the requirements and the customer's expectations. Instead of creating arguments and finger-pointing, you can simply continue to monitor velocity and use it in your planning and budgeting. That's the other good thing - it's an adaptive approach. The customer is allowed to update the product backlog after each iteration - changing priorities, adding some new requirements or perhaps removing some that no longer make sense or just happened to emerge naturally as other features were being developed. The developers can then review and update their estimates and provide an ever more accurate planning picture. It's not very hard to track the &lt;a href="http://sehlhorst.smugmug.com/photos/98842056-M.jpg"&gt;velocity as a curve&lt;/a&gt; that makes the progress being made very clear to all parties involved.&lt;div class="blogger-post-footer"&gt;&lt;img width='1' height='1' src='https://blogger.googleusercontent.com/tracker/10784478-7953938800697990896?l=vladimirlevin.blogspot.com' alt='' /&gt;&lt;/div&gt;</content><link rel='replies' type='application/atom+xml' href='http://vladimirlevin.blogspot.com/feeds/7953938800697990896/comments/default' title='Post Comments'/><link rel='replies' type='text/html' href='http://www.blogger.com/comment.g?blogID=10784478&amp;postID=7953938800697990896' title='0 Comments'/><link rel='edit' type='application/atom+xml' href='http://www.blogger.com/feeds/10784478/posts/default/7953938800697990896'/><link rel='self' type='application/atom+xml' href='http://www.blogger.com/feeds/10784478/posts/default/7953938800697990896'/><link rel='alternate' type='text/html' href='http://vladimirlevin.blogspot.com/2007/10/estimating-software-development.html' title='Estimating Software Development'/><author><name>Vladimir Levin</name><uri>http://www.blogger.com/profile/09680919094932667147</uri><email>noreply@blogger.com</email><gd:image rel='http://schemas.google.com/g/2005#thumbnail' width='21' height='32' src='http://2.bp.blogspot.com/_zD5Hp0u_Wi0/SqSQJLR_0_I/AAAAAAAAADE/l8j4ET6y63E/S220/vlad_korean.jpg'/></author><thr:total>0</thr:total></entry><entry><id>tag:blogger.com,1999:blog-10784478.post-1133033788010616485</id><published>2007-09-17T08:04:00.000-07:00</published><updated>2007-09-17T08:16:47.631-07:00</updated><title type='text'>Palisaro Wall Tutorial (flash using haXe)</title><content type='html'>I've written a &lt;a href="http://www.geocities.com/vladimir_levin/palisaro_wall_tutorial/"&gt;tutorial&lt;/a&gt; for a flash game called &lt;a href="http://disemia.com/palisaro/Palisaro.swf"&gt;Palisaro &lt;/a&gt;that was developed by a friend of mine, &lt;a href="http://disemia.com/software/index.html"&gt;Eda-qa&lt;/a&gt;. I have a feeling flash perhaps wasn't designed for interactive applications as my friend tells me tweaking his code for performance was one of the most time-consuming aspects of getting the game working. This tutorial is about recognizing walls around areas, and I think it's interesting because the solution may be a bit counter-intuitive. When we were originally discussing it by e-mail, I was surprised the algorithm didn't focus on the wall elements themselves, but maybe that's just me. In any case, if you're interested in developing an application in flash, you may find this &lt;a href="http://www.geocities.com/vladimir_levin/palisaro_wall_tutorial"&gt;tutorial &lt;/a&gt;helpful. I found &lt;a href="http://haxe.org/"&gt;haXe &lt;/a&gt;to be a very nice language to look at and it definitely comes across as a language of choice for anyone with a C++/Java background who wants to write flash applications.&lt;div class="blogger-post-footer"&gt;&lt;img width='1' height='1' src='https://blogger.googleusercontent.com/tracker/10784478-1133033788010616485?l=vladimirlevin.blogspot.com' alt='' /&gt;&lt;/div&gt;</content><link rel='replies' type='application/atom+xml' href='http://vladimirlevin.blogspot.com/feeds/1133033788010616485/comments/default' title='Post Comments'/><link rel='replies' type='text/html' href='http://www.blogger.com/comment.g?blogID=10784478&amp;postID=1133033788010616485' title='0 Comments'/><link rel='edit' type='application/atom+xml' href='http://www.blogger.com/feeds/10784478/posts/default/1133033788010616485'/><link rel='self' type='application/atom+xml' href='http://www.blogger.com/feeds/10784478/posts/default/1133033788010616485'/><link rel='alternate' type='text/html' href='http://vladimirlevin.blogspot.com/2007/09/palisaro-wall-tutorial-flash-using-haxe.html' title='Palisaro Wall Tutorial (flash using haXe)'/><author><name>Vladimir Levin</name><uri>http://www.blogger.com/profile/09680919094932667147</uri><email>noreply@blogger.com</email><gd:image rel='http://schemas.google.com/g/2005#thumbnail' width='21' height='32' src='http://2.bp.blogspot.com/_zD5Hp0u_Wi0/SqSQJLR_0_I/AAAAAAAAADE/l8j4ET6y63E/S220/vlad_korean.jpg'/></author><thr:total>0</thr:total></entry><entry><id>tag:blogger.com,1999:blog-10784478.post-17149457834216669</id><published>2007-08-22T13:01:00.000-07:00</published><updated>2007-08-22T13:11:38.153-07:00</updated><title type='text'>How to Hire (Programmers)</title><content type='html'>I've been interviewed for software development positions many times since I started working in the so-called IT industry. Generally I've been disappointed by the kinds of questions people ask. Either they ask lots of soft questions or they ask very academic "puzzle" types of questions. The problem with the soft questions is that a good talker can come up with convincing answers even if he/she is utterly incompetent. On the other hand, the puzzle questions leave me cold. It's quite possible to be good at solving such puzzles without being a good developer, and vice versa. Often the puzzle questions, if they have anything to do with programming at all, emphasize how to optimize certain algorithms. The truth is that an over-emphasis on optimization is one of the most common problems I see. It makes code much harder to work with, often without a tangible benefit. Don't get me wrong, I'm not saying that being able to communicate with people isn't important or that one ought to hire dumb people, but I think the industry lacks a sense of the overall qualities to look for. Thankfully, Marc Andreessen, of Netscape fame, has written (in my opinion) the definitive guide to hiring software developers. &lt;br /&gt;&lt;br /&gt;&lt;a href="http://blog.pmarca.com/2007/06/how_to_hire_the.html"&gt;http://blog.pmarca.com/2007/06/how_to_hire_the.html&lt;/a&gt;&lt;div class="blogger-post-footer"&gt;&lt;img width='1' height='1' src='https://blogger.googleusercontent.com/tracker/10784478-17149457834216669?l=vladimirlevin.blogspot.com' alt='' /&gt;&lt;/div&gt;</content><link rel='replies' type='application/atom+xml' href='http://vladimirlevin.blogspot.com/feeds/17149457834216669/comments/default' title='Post Comments'/><link rel='replies' type='text/html' href='http://www.blogger.com/comment.g?blogID=10784478&amp;postID=17149457834216669' title='0 Comments'/><link rel='edit' type='application/atom+xml' href='http://www.blogger.com/feeds/10784478/posts/default/17149457834216669'/><link rel='self' type='application/atom+xml' href='http://www.blogger.com/feeds/10784478/posts/default/17149457834216669'/><link rel='alternate' type='text/html' href='http://vladimirlevin.blogspot.com/2007/08/how-to-hire-programmers.html' title='How to Hire (Programmers)'/><author><name>Vladimir Levin</name><uri>http://www.blogger.com/profile/09680919094932667147</uri><email>noreply@blogger.com</email><gd:image rel='http://schemas.google.com/g/2005#thumbnail' width='21' height='32' src='http://2.bp.blogspot.com/_zD5Hp0u_Wi0/SqSQJLR_0_I/AAAAAAAAADE/l8j4ET6y63E/S220/vlad_korean.jpg'/></author><thr:total>0</thr:total></entry><entry><id>tag:blogger.com,1999:blog-10784478.post-3451825921193078738</id><published>2007-07-12T08:41:00.000-07:00</published><updated>2010-07-24T00:56:46.917-07:00</updated><title type='text'>Tinkerers, Platonists, and Communicators</title><content type='html'>&lt;a href="http://vladimirlevin.blogspot.com/2006/07/ravis-post-about-boring-enterprise.html"&gt;I've written on this topic before&lt;/a&gt; but lately I've been thinking some more about the differences of perspective people have about software development and I came up with the idea that there are three pure personality types in software development: Tinkerers, Platonists, and Communicators. That's my attempt to neologize a la Martin Fowler by the way! Each type tends to focus on one aspect of development over others, and I think we all tend to fall into the trap emphasizing our own inclinations and downplaying the importance of the other perspectives. I suspect most of us have some attributes of each type but that developers can probably be identified as mostly leaning toward one of these types more than the others. Here then are my descriptions of each type!&lt;br /&gt;&lt;br /&gt;The Tinkerer: The tinkerer is someone who generally thinks of programming as an adjunct to other things. Some examples: A stock broker might write some macros in excel to crunch some financial numbers. An engineer might need to write some drivers for a piece of hardware s/he designed. A network administrator might cook up some scripts in perl to help manage repetitive tasks or analyse network traffic. The tinkerer's sweet spot is in getting things configured, finding ad-hoc optimizations, and writing quick and dirty hacks that get the job done. The big weakness of the tinkerer is scaling software to the point where it has to be maintained on an ongoing basis, especially if multiple developers become involved. Tinkerers may not to recognize such risks and are generally comfortable with a certain amount of messiness. Tinkerers are great people to have on a team when you need to figure out how to make something work - they love finding out about all of the different options a piece of software or hardware has and can find a way to make something work even if the tools that are being used don't make it easy. I think &lt;a href="http://en.wikipedia.org/wiki/Linus_Torvalds"&gt;Linus Torvalds&lt;/a&gt; is an archetypal tinkerer.&lt;br /&gt;&lt;br /&gt;The Platonist: The platonist is in many ways the diametric opposite of the tinkerer. They're not interested in nitty gritty details. They enjoy working with pure and abstract ideas and they want to solve problems in the most general way possible. They tend not to be happy with solutions that are "good enough for now." Platonists are generally not inclined toward empirical or iterative approaches to developing software because they see software as something like a math problem - something to be analyzed completely and solved in its entirety. Joel Spolsky jokingly referred to the kind of people I'm talking about here as "&lt;a href="http://www.joelonsoftware.com/articles/fog0000000018.html"&gt;Architecture Astronauts&lt;/a&gt;," which highlights their main weaknesses: Platonists can fall into the trap of spending far too much time trying to fully analyze something leading to the infamous analysis paralysis that software teams are often subject to. Platonists also tend to produce designs that are so abstract it's difficult to actually work with them. You know you're dealing with software designed by a platonist if it can theoretically do anything you want it to but it's hard to figure out how to make it print hello world. A good platonist is great to have around when you need to apply or develop a sophisticated algorithm. They enjoy most being set loose on an intellectually challenging but well defined problem. I think &lt;a href="http://norvig.com/"&gt;Peter Norvig&lt;/a&gt; is a platonist and of course &lt;a href="http://en.wikipedia.org/wiki/Edsger_Dijkstra"&gt;Dijkstra&lt;/a&gt; was the original platonist!&lt;br /&gt;&lt;br /&gt;The Communicator: Communicators think of software develoment more as human language  designed for human consumption than as an abstract mathematical concept. They focus on expressing ideas clearly in code. Both tinkerers and platonists would tend to leave a piece of code alone once it's working properly, but to a communicator it's not good enough for code merely to be correct. It also has to be maintainable. Communicators can focus so much on the quality of their code that they might miss the point that a given situation calls for a well-defined algorithm. They also don't enjoy figuring out how to hack something just to make it work, which wether they like it or not, is often necessary. Another problem I've seen with this style of development is that communicators can become overly enthusiastic in their efforts to shape code, so instead of writing code that is concise and simple they wind up producing bloated class hierarchies and abusing design patterns. I think communicators may share this type of weakness with the platonists. Good communicators are great to have around as people who remove duplication from code and generally clean it up. They can be helpful in translating a sophisticated algorithm into  code that can be readily understood and if there is some gnarly code in the system, they at least will write adaptors that encasulate that code behind a clean interface. Developers who are good communicators often work well interacting with users and customers to translate and organize requirements that may seem arbitrary and complex into code that is consistent and simple. &lt;a href="http://en.wikipedia.org/wiki/Kent_Beck"&gt;Kent Beck&lt;/a&gt; comes across as a very prototypical communicator. After all refactoring, one of the main practices in XP, concerns itself with the idea of altering the structure of code without changing what it does. I think &lt;a href="http://www.martinfowler.com/"&gt;Martin Fowler&lt;/a&gt; is another good example of a communicator.&lt;br /&gt;&lt;br /&gt;All three of these "personas" have some strengths and some weaknesses. Also if you find that you tend strongly toward one of these poles, it may be worthwhile to expand your consciousness a bit and to force yourself to develop in the other directions as well!&lt;div class="blogger-post-footer"&gt;&lt;img width='1' height='1' src='https://blogger.googleusercontent.com/tracker/10784478-3451825921193078738?l=vladimirlevin.blogspot.com' alt='' /&gt;&lt;/div&gt;</content><link rel='replies' type='application/atom+xml' href='http://vladimirlevin.blogspot.com/feeds/3451825921193078738/comments/default' title='Post Comments'/><link rel='replies' type='text/html' href='http://www.blogger.com/comment.g?blogID=10784478&amp;postID=3451825921193078738' title='3 Comments'/><link rel='edit' type='application/atom+xml' href='http://www.blogger.com/feeds/10784478/posts/default/3451825921193078738'/><link rel='self' type='application/atom+xml' href='http://www.blogger.com/feeds/10784478/posts/default/3451825921193078738'/><link rel='alternate' type='text/html' href='http://vladimirlevin.blogspot.com/2007/07/tinkerers-platonists-and-communicators.html' title='Tinkerers, Platonists, and Communicators'/><author><name>Vladimir Levin</name><uri>http://www.blogger.com/profile/09680919094932667147</uri><email>noreply@blogger.com</email><gd:image rel='http://schemas.google.com/g/2005#thumbnail' width='21' height='32' src='http://2.bp.blogspot.com/_zD5Hp0u_Wi0/SqSQJLR_0_I/AAAAAAAAADE/l8j4ET6y63E/S220/vlad_korean.jpg'/></author><thr:total>3</thr:total></entry><entry><id>tag:blogger.com,1999:blog-10784478.post-7023932974049391533</id><published>2007-06-28T10:16:00.000-07:00</published><updated>2007-06-28T19:17:48.028-07:00</updated><title type='text'>Software Development vs. Engineering</title><content type='html'>&lt;div class="CommentText"&gt;I recently read Kelly Waters' blog entry &lt;a href="http://kw-agiledevelopment.blogspot.com/2007/06/scrum-agile-development-uncommon-sense.html"&gt;about the 'uncommon sense' of agile development&lt;/a&gt;. Kelly's argument is that when you strip Scrum of its jargon, the ideas are self evident andjust common sense. So why is there so much controvery then? I think one of the problems is that software has been saddled with an analogy between software and civil engineering, e.g. contruction of bridges, buildings and such things. This way of looking at things continues to influence organizations to this day.&lt;br /&gt;&lt;div class="CommentText2"&gt;                  &lt;div class="CommentText3"&gt;&lt;p&gt;I believe one of the key reasons for the emphasis on up-front requirements and up-front design phases in the world of software stems from the idea that developing software is like engineering or architecture. In these areas one spends a lot of time on design, and only once the design has been completed does one actually engage in the activity of construction.  If one takes this analogy to be valid, then developing a piece of software iteratively looks foolish: Would it be reasonable to design a skyscraper by first building a bungalo and using the feedback from that to build a two story house, etc. until one has a skyscraper? Of course not. I think that for the most part the approach that's currently used in bridge building and architecture makes good sense for those disciplines, but it doesn't translate nearly as well to the world of software. In my opinion, there are three primary dimensions that make software a rather different animal:&lt;br /&gt;&lt;/p&gt; &lt;p&gt;1) One can use engineering formulas in a practical way to validate a design ahead of time, say to make sure a bridge will stand up to a certain load of traffic. Software however is not subject to the contraints of physics, so the applicability of this kind of technique is limited to the fairly narrow area of algorithms. It may make sense to make sure a scheduling or path finding algorithm is correct for example, but does that kind of idea apply to a software system in general? Are there any engineering formulas that would insure that a design for accounting software will meet its users requirements?&lt;br /&gt;&lt;/p&gt; &lt;p&gt;2) Models are not nearly as useful in software development as they are in engineering. Models and simulations of bridges and buildings get pretty close to the reality of what one is trying to build without actually having to build it. One can look at a scale-model of a building or a 3-d computer simulation and get a lot of really valuable feedback. Things like ERD diagrams and various UML constructs, e.g. class diagrams, sequence diagrams, are far less kinesthetic - I'd say they're even less expressive than an engineering blueprint. Does some collection of classes and methods really represent a good solution for a given problem? Yes? No? Maybe? I've found it very difficult to anticipate from such diagrams what it will be like to actually work with the code.&lt;br /&gt;&lt;/p&gt; &lt;p&gt;3) Finally, buildings and bridges are designed &lt;span style="font-style: italic;"&gt;to resist change&lt;/span&gt;. Once you've built something like that, it will remain that way until it needs to be replaced - every aspect of the effort is focused on that goal. Would anyone consider adding a few extra stories to an existing skyscraper,  or adding a lane to a bridge that's already been built? On the other hand, most software systems must stand up to constant change during their life spans and those changes are often  substantial. One's approach to software design should be flexible and adapt to future changes.&lt;br /&gt;&lt;/p&gt; &lt;/div&gt;                 &lt;/div&gt;                &lt;/div&gt;&lt;div class="blogger-post-footer"&gt;&lt;img width='1' height='1' src='https://blogger.googleusercontent.com/tracker/10784478-7023932974049391533?l=vladimirlevin.blogspot.com' alt='' /&gt;&lt;/div&gt;</content><link rel='replies' type='application/atom+xml' href='http://vladimirlevin.blogspot.com/feeds/7023932974049391533/comments/default' title='Post Comments'/><link rel='replies' type='text/html' href='http://www.blogger.com/comment.g?blogID=10784478&amp;postID=7023932974049391533' title='0 Comments'/><link rel='edit' type='application/atom+xml' href='http://www.blogger.com/feeds/10784478/posts/default/7023932974049391533'/><link rel='self' type='application/atom+xml' href='http://www.blogger.com/feeds/10784478/posts/default/7023932974049391533'/><link rel='alternate' type='text/html' href='http://vladimirlevin.blogspot.com/2007/06/software-development-vs-engineering.html' title='Software Development vs. Engineering'/><author><name>Vladimir Levin</name><uri>http://www.blogger.com/profile/09680919094932667147</uri><email>noreply@blogger.com</email><gd:image rel='http://schemas.google.com/g/2005#thumbnail' width='21' height='32' src='http://2.bp.blogspot.com/_zD5Hp0u_Wi0/SqSQJLR_0_I/AAAAAAAAADE/l8j4ET6y63E/S220/vlad_korean.jpg'/></author><thr:total>0</thr:total></entry><entry><id>tag:blogger.com,1999:blog-10784478.post-2205786397450048489</id><published>2007-06-11T13:33:00.000-07:00</published><updated>2007-06-13T09:52:08.040-07:00</updated><title type='text'>Little Shop Of Sudoku Horrors</title><content type='html'>I've recently run across a few examples of unorthodox Sudoku solver programs which are kind of entertaining in a way, but also frightening. Here's an example using &lt;a href="http://www.vsj.co.uk/articles/display.asp?id=540"&gt;sql&lt;/a&gt;, and here's another example using &lt;a href="http://n01senet.blogspot.com/2007/05/sudoku-by-regex.html"&gt;regular expressions.&lt;/a&gt;  I've spent just enough time looking at these solutions to be horrified. I certainly wouldn't want to have to maintain such code, and it confirms my general opinion that sql and regular expressions are appropriate for a limited range of situations and should not be used for general programming. Of course it's kind of amusing to see that it's &lt;span style="font-style: italic;"&gt;possible&lt;/span&gt; to write a sudoku solver with these technologies in the same way that &lt;a href="http://www.stmarys-ca.edu/75/phonebooth.jpg"&gt;this&lt;/a&gt; is amusing.&lt;br /&gt;&lt;br /&gt;Additional sudoku horrors: Sudoku in &lt;a href="http://homepage.mac.com/bprice1949/sudokucobol.html"&gt;cobol&lt;/a&gt;! &lt;a href="http://markbyers.com/moinmoin/moin.cgi/ShortestSudokuSolver"&gt;Shortest sudoku solvers&lt;/a&gt;! These are kind of cool, but also teach the lesson that writing maintainable code isn't just about making it as concise as possible!&lt;br /&gt;&lt;br /&gt;Reference: Peter Norvig's &lt;a href="http://norvig.com/sudoku.html"&gt;python code&lt;/a&gt;.  This code is certainly clean and compact (I do take issue a bit with his constraint propagation. You can have a look at &lt;a href="http://www.geocities.com/vladimir_levin/sudoku.html"&gt;my java code&lt;/a&gt; example for more details). In any case, much nicer than the craziness above.&lt;div class="blogger-post-footer"&gt;&lt;img width='1' height='1' src='https://blogger.googleusercontent.com/tracker/10784478-2205786397450048489?l=vladimirlevin.blogspot.com' alt='' /&gt;&lt;/div&gt;</content><link rel='replies' type='application/atom+xml' href='http://vladimirlevin.blogspot.com/feeds/2205786397450048489/comments/default' title='Post Comments'/><link rel='replies' type='text/html' href='http://www.blogger.com/comment.g?blogID=10784478&amp;postID=2205786397450048489' title='2 Comments'/><link rel='edit' type='application/atom+xml' href='http://www.blogger.com/feeds/10784478/posts/default/2205786397450048489'/><link rel='self' type='application/atom+xml' href='http://www.blogger.com/feeds/10784478/posts/default/2205786397450048489'/><link rel='alternate' type='text/html' href='http://vladimirlevin.blogspot.com/2007/06/how-not-to-solve-sudoku.html' title='Little Shop Of Sudoku Horrors'/><author><name>Vladimir Levin</name><uri>http://www.blogger.com/profile/09680919094932667147</uri><email>noreply@blogger.com</email><gd:image rel='http://schemas.google.com/g/2005#thumbnail' width='21' height='32' src='http://2.bp.blogspot.com/_zD5Hp0u_Wi0/SqSQJLR_0_I/AAAAAAAAADE/l8j4ET6y63E/S220/vlad_korean.jpg'/></author><thr:total>2</thr:total></entry><entry><id>tag:blogger.com,1999:blog-10784478.post-1206116069616328527</id><published>2007-05-30T10:44:00.000-07:00</published><updated>2007-05-30T10:47:11.484-07:00</updated><title type='text'>Standish Group Project Data</title><content type='html'>There are some interesting articles/discussions on InfoQ concerning data about project successes and failures.&lt;br /&gt;&lt;br /&gt;&lt;a href="http://www.infoq.com/articles/Interview-Johnson-Standish-CHAOS"&gt;Interview with Jim Johnson of Standish Group&lt;/a&gt;&lt;br /&gt;&lt;a href="http://www.infoq.com/articles/chaos-1998-failure-stats"&gt;Why Were Project Failures Up and Cost Overruns Down in 1998&lt;/a&gt;&lt;div class="blogger-post-footer"&gt;&lt;img width='1' height='1' src='https://blogger.googleusercontent.com/tracker/10784478-1206116069616328527?l=vladimirlevin.blogspot.com' alt='' /&gt;&lt;/div&gt;</content><link rel='replies' type='application/atom+xml' href='http://vladimirlevin.blogspot.com/feeds/1206116069616328527/comments/default' title='Post Comments'/><link rel='replies' type='text/html' href='http://www.blogger.com/comment.g?blogID=10784478&amp;postID=1206116069616328527' title='0 Comments'/><link rel='edit' type='application/atom+xml' href='http://www.blogger.com/feeds/10784478/posts/default/1206116069616328527'/><link rel='self' type='application/atom+xml' href='http://www.blogger.com/feeds/10784478/posts/default/1206116069616328527'/><link rel='alternate' type='text/html' href='http://vladimirlevin.blogspot.com/2007/05/standish-group-project-data.html' title='Standish Group Project Data'/><author><name>Vladimir Levin</name><uri>http://www.blogger.com/profile/09680919094932667147</uri><email>noreply@blogger.com</email><gd:image rel='http://schemas.google.com/g/2005#thumbnail' width='21' height='32' src='http://2.bp.blogspot.com/_zD5Hp0u_Wi0/SqSQJLR_0_I/AAAAAAAAADE/l8j4ET6y63E/S220/vlad_korean.jpg'/></author><thr:total>0</thr:total></entry><entry><id>tag:blogger.com,1999:blog-10784478.post-3206257384719951927</id><published>2007-05-23T17:39:00.002-07:00</published><updated>2007-05-23T17:45:13.743-07:00</updated><title type='text'>The Way Of Testivus</title><content type='html'>I recently read &lt;a href="http://www.agitar.com/downloads/TheWayOfTestivus.pdf"&gt;The Way Of Testivus&lt;/a&gt;. It was so refreshingly light-hearted, yet with a depth of wisdom at its light heart. Very enjoyable indeed. I'd like to rave about it some more, but really it speaks for itself. Just read and enjoy. Less Dogma! More Karma!&lt;div class="blogger-post-footer"&gt;&lt;img width='1' height='1' src='https://blogger.googleusercontent.com/tracker/10784478-3206257384719951927?l=vladimirlevin.blogspot.com' alt='' /&gt;&lt;/div&gt;</content><link rel='replies' type='application/atom+xml' href='http://vladimirlevin.blogspot.com/feeds/3206257384719951927/comments/default' title='Post Comments'/><link rel='replies' type='text/html' href='http://www.blogger.com/comment.g?blogID=10784478&amp;postID=3206257384719951927' title='0 Comments'/><link rel='edit' type='application/atom+xml' href='http://www.blogger.com/feeds/10784478/posts/default/3206257384719951927'/><link rel='self' type='application/atom+xml' href='http://www.blogger.com/feeds/10784478/posts/default/3206257384719951927'/><link rel='alternate' type='text/html' href='http://vladimirlevin.blogspot.com/2007/05/way-of-testivus_1744.html' title='The Way Of Testivus'/><author><name>Vladimir Levin</name><uri>http://www.blogger.com/profile/09680919094932667147</uri><email>noreply@blogger.com</email><gd:image rel='http://schemas.google.com/g/2005#thumbnail' width='21' height='32' src='http://2.bp.blogspot.com/_zD5Hp0u_Wi0/SqSQJLR_0_I/AAAAAAAAADE/l8j4ET6y63E/S220/vlad_korean.jpg'/></author><thr:total>0</thr:total></entry><entry><id>tag:blogger.com,1999:blog-10784478.post-2244225352931796321</id><published>2007-05-12T00:31:00.000-07:00</published><updated>2007-05-12T21:37:52.312-07:00</updated><title type='text'>Solving Sudoku Using TDD</title><content type='html'>Thanks to some encouragement from Ravi suggesting I try my hand at a Sudoku solver, I've written up my &lt;a href="http://www.geocities.com/vladimir_levin/sudoku.html"&gt;experiences writing one using TDD&lt;/a&gt;. My main goal was to see if using TDD would be helpful. I thought it was. However, you can judge for yourself.  I think the experience confirmed my opinion that using TDD is not a magic wand that allows algorithms to just "emerge,"  but on the other hand it is a useful tool to move forward in small steps and to design code to be as intention-revealing as possible.&lt;div class="blogger-post-footer"&gt;&lt;img width='1' height='1' src='https://blogger.googleusercontent.com/tracker/10784478-2244225352931796321?l=vladimirlevin.blogspot.com' alt='' /&gt;&lt;/div&gt;</content><link rel='replies' type='application/atom+xml' href='http://vladimirlevin.blogspot.com/feeds/2244225352931796321/comments/default' title='Post Comments'/><link rel='replies' type='text/html' href='http://www.blogger.com/comment.g?blogID=10784478&amp;postID=2244225352931796321' title='2 Comments'/><link rel='edit' type='application/atom+xml' href='http://www.blogger.com/feeds/10784478/posts/default/2244225352931796321'/><link rel='self' type='application/atom+xml' href='http://www.blogger.com/feeds/10784478/posts/default/2244225352931796321'/><link rel='alternate' type='text/html' href='http://vladimirlevin.blogspot.com/2007/05/solving-sudoku-using-tdd.html' title='Solving Sudoku Using TDD'/><author><name>Vladimir Levin</name><uri>http://www.blogger.com/profile/09680919094932667147</uri><email>noreply@blogger.com</email><gd:image rel='http://schemas.google.com/g/2005#thumbnail' width='21' height='32' src='http://2.bp.blogspot.com/_zD5Hp0u_Wi0/SqSQJLR_0_I/AAAAAAAAADE/l8j4ET6y63E/S220/vlad_korean.jpg'/></author><thr:total>2</thr:total></entry><entry><id>tag:blogger.com,1999:blog-10784478.post-6604403446602709625</id><published>2007-04-24T14:32:00.001-07:00</published><updated>2009-10-06T17:37:41.645-07:00</updated><title type='text'>TDD Is Not An Algorithm Generator!</title><content type='html'>[Update: &lt;a href="http://vladimirlevin.blogspot.com/2009/09/spy-vs-spy.html"&gt;more on this topic&lt;/a&gt;]&lt;br /&gt;&lt;br /&gt;In his blog, Ravi &lt;a href="http://ravimohan.blogspot.com/2007/04/learning-from-sudoku-solvers.html"&gt;compares Ron Jeffries working out a sudoku solver using TDD with Peter Norvig's implementation&lt;/a&gt;.&lt;br /&gt;&lt;br /&gt;Now, what can we learn from the two efforts? Peter does not use TDD to solve the problem, yet his solution is compact and complete, whereas Ron's TDD effort remains just a partial solution. Does that mean that TDD is inferior to design up front? I do not believe that's the point Ravi was trying to make, but perhaps he was trying to say that TDD is not an algorithm generator. In that respect, I completely agree. In fact, one of the first rules I teach my students when I am doing a TDD workshop or teaching a course is precisely that &lt;span style="font-weight: bold; font-style: italic;"&gt;TDD is &lt;/span&gt;&lt;span style="font-weight: bold; font-style: italic;"&gt;not&lt;/span&gt;&lt;span style="font-weight: bold; font-style: italic;"&gt; an algorithm generator&lt;/span&gt;! Solving sudoku is just the kind of problem you want to find an algorithm for first, then implement that algorithm. This is not a question of up-front design. It's just common sense: It's perfectly reasonable to know conceptually how to solve sudoku puzzles before writing any code. Else how would you know whether any of the intermediate methods that you so diligently write tests for will be useful in the end?&lt;br /&gt;&lt;br /&gt;There is a real gap between a design, which is a particular structure of code, and an algorithm, which is a description of how to solve a problem. An algorithm can be expressed in any form you choose. It can be a mathematical notation or it can be written down in plain english, or it can live in your head, but if an algorithm is required to complete a story, you should certainly know what it is before you engage in writing your production code. If you doubt what I'm saying, consider a story where I ask you to write code to encrypt and decrypt files. Would you just start hacking out methods (using TDD or otherwise)? You'd be lucky to develop a trivial cipher. You need to choose a cryptographic algorithm before you begin any programming. Once you do start with the programming, I would certainly recommend using TDD as a way of &lt;span style="font-weight: bold;"&gt;&lt;span style="font-style: italic;"&gt;designing&lt;/span&gt;&lt;/span&gt; the code.&lt;br /&gt;&lt;br /&gt;Let's say you're faced with a problem where you &lt;span style="font-weight: bold; font-style: italic;"&gt;want &lt;/span&gt;&lt;span style="font-style: italic;"&gt;&lt;/span&gt;to find the right algorithm yourself, either because you have to or just because you enjoy the challenge. Writing some code to solve a simpler part of the problem may be a good way to start. That approach worked for Peter in his solution to Sudoku - I doubt it's guaranteed to work all the time. In any case, when you're hunting for an algorithm, any code you write should be considered provisional. The main purpose is not to produce high quality maintainable code, it's just to see if getting part way toward a solution will trigger any additional insights. Again, it's once you've understood the correct algorithm that you can begin writing the production code.&lt;br /&gt;&lt;br /&gt;I certainly think Ron's example is not a very good indication of how TDD should work. I am also disheartened that Ron doesn't clearly make the point that he is looking for an algorithm. Therefore his efforts to refactor his code during the tdd process, are far too premature. Based on Peter's solution, I'd say Ron never even gets half way toward the correct algorithm and wastes his last few articles on refactoring to objects instead of doing anything particularly useful or enlightening. When you're in an investigative mode where you don't even know how to solve your problem, that harly seems like the time to solidify the design. Even if you're doing agile development, keep in mind that for each XP story, you should be certain that you know at least informally in your own mind the steps needed to solve the problem.  Trying to offer TDD as an algorithm generator is dopey and it's just going to make it easy for people not to take TDD seriously as a valid design technique.&lt;br /&gt;&lt;br /&gt;So what is the purpose of TDD then? One goal of TDD is to reduce the need to determine ahead of time which classes and methods you're going to implement for an entire story. There's a large body of shared experience in the developer community that trying to anticipate such things tends to lead to paralysis where nothing useful gets done and/or produces bloated, over-designed code. Instead, you can develop one aspect of the story at a time, using each test to keep yourself moving forward and refactoring the design as you go along - think of TDD then as a ratchet or a  belay device in climbing.  One of the principles of agile development is that it's generally &lt;span style="font-weight: bold; font-style: italic;"&gt;not a good idea to try to&lt;/span&gt; &lt;span style="font-style: italic;"&gt;&lt;span style="font-weight: bold;"&gt;comprehensively understand a whole&lt;/span&gt;&lt;/span&gt; &lt;span style="font-weight: bold;"&gt;&lt;span style="font-style: italic;"&gt;project&lt;span style="font-style: italic;"&gt;&lt;span style="font-weight: bold;"&gt; &lt;/span&gt;&lt;/span&gt;&lt;/span&gt;&lt;/span&gt;(or a big part of it) up-front, as is often done in waterfall-ish methodologies. However, that doesn't mean you need to begin every story blindly without understanding how to solve that particular problem.&lt;br /&gt;&lt;br /&gt;&lt;span&gt;Updates: UncleBob makes a good comment on reddit:&lt;/span&gt;&lt;span&gt; &lt;a href="http://programming.reddit.com/info/1kth0/comments/c1lkvh"&gt;http://programming.reddit.com/info/1kth0/comments/c1lkvh&lt;/a&gt;; Read about my &lt;a href="http://vladimirlevin.blogspot.com/2007/05/solving-sudoku-using-tdd.html"&gt;TDD Sudoku effort&lt;/a&gt;&lt;br /&gt;&lt;/span&gt;&lt;div class="blogger-post-footer"&gt;&lt;img width='1' height='1' src='https://blogger.googleusercontent.com/tracker/10784478-6604403446602709625?l=vladimirlevin.blogspot.com' alt='' /&gt;&lt;/div&gt;</content><link rel='edit' type='application/atom+xml' href='http://www.blogger.com/feeds/10784478/posts/default/6604403446602709625'/><link rel='self' type='application/atom+xml' href='http://www.blogger.com/feeds/10784478/posts/default/6604403446602709625'/><link rel='alternate' type='text/html' href='http://vladimirlevin.blogspot.com/2007/04/tdd-is-not-algorithm-generator.html' title='TDD Is Not An Algorithm Generator!'/><author><name>Vladimir Levin</name><uri>http://www.blogger.com/profile/09680919094932667147</uri><email>noreply@blogger.com</email><gd:image rel='http://schemas.google.com/g/2005#thumbnail' width='21' height='32' src='http://2.bp.blogspot.com/_zD5Hp0u_Wi0/SqSQJLR_0_I/AAAAAAAAADE/l8j4ET6y63E/S220/vlad_korean.jpg'/></author></entry><entry><id>tag:blogger.com,1999:blog-10784478.post-2586261896965335659</id><published>2007-04-22T16:36:00.000-07:00</published><updated>2007-04-22T19:40:34.640-07:00</updated><title type='text'>Snake-Oil Salesmen, Process Skepticism, and Why I am Not a "Post-Agilist"</title><content type='html'>&lt;blockquote&gt;The optimist thinks that this is the best of all possible worlds, and the pessimist knows it.&lt;br /&gt;-- J. Robert Oppenheimer, "Bulletin of Atomic Scientists"&lt;br /&gt;&lt;br /&gt;&lt;/blockquote&gt;While I am a strong proponent of agile methods, I've witnessed a number of people I respect writing about being skeptical of agile processes and complaining about evangelists who try to sell methodology without really knowing what they're talking about. For example, Jonathan Kohl has written about &lt;a href="http://www.kohl.ca/blog/archives/000166.html"&gt;Post-Agilism&lt;/a&gt; where he states :&lt;br /&gt;&lt;blockquote&gt;Personally, I like Agile methods, but I have also seen plenty of failures. I've witnessed that merely following a process, no matter how good it is, does not guarantee success. I've also learned that no matter what process you follow, if you don't have skilled people on the team, you are going to find it hard to be successful.&lt;br /&gt;&lt;/blockquote&gt;&lt;br /&gt;Ravi Mohan has written of Agile as a &lt;a href="http://ravimohan.blogspot.com/2006/01/agile-religion-and-need-for-merciless.html"&gt;religion&lt;/a&gt;, "with its holy books, many patriarchs, its churches, and  commandments." In his blog, Ravi also frequently decries the lack of actual programming experience demonstrated by many self-professed gurus to back up their claims.&lt;br /&gt;&lt;br /&gt;On a certain level I agree. It seems evident that any movement, as it grows beyond a certain point, becomes vulnerable to distortion, both by the well meaning but ignorant, and also by those who cynically aim to make a buck from whatever is trendy today. Agile is no exception. One thing I stress whenever I talk about agile methods is that the agile manifesto is self-referencing. The first statement (Ravi would perhaps say commandment!) of the &lt;a href="http://agilemanifesto.org/"&gt;manifesto&lt;/a&gt; is clear:&lt;br /&gt;&lt;br /&gt;&lt;div style="text-align: center;"&gt;&lt;span style="font-weight: bold;"&gt;Individuals and interactions&lt;/span&gt; over processes and tools&lt;br /&gt;&lt;/div&gt;&lt;span style="font-size:100%;"&gt;&lt;/span&gt;&lt;br /&gt;Those "processes and tools" include the methods of Scrum and XP! If you're working on an agile project and the people on the project are trying to blindly follow some agile practice when it clearly doesn't make sense, they are violating the spirit of agile development: &lt;span style="font-style: italic;"&gt;Ipso facto&lt;/span&gt;, you must use your knowledge of what's actually happening on your particular project, your team, at a particular point in time to decide what to do next. Everything else is just a guideline.&lt;br /&gt;&lt;br /&gt;However, things are unfortunately not so simple because it is often not clear when you should abandon a given practice. Let's say you think that something isn't testable and you give up test-first development; then you decide that a given feature really requires a lot of up-front design and you give up iterations. Before long you've entirely given up all the essential aspects of what agile software development is about! Following an agile practice is therefore always a delicate balancing act. You must respond empirically to reality, but you must learn the practical value of agile practices. I've found that many of these practices are worth defending. For example, at times I have been tempted to abandon test-first development when testing became difficult, but upon deeper consideration I realized that there was something wrong with the way I was approaching my problem, and that was the real culprit that made the test-first approach problematic. By re-thinking my approach, I found a way back to test-first development and its benefits.&lt;br /&gt;&lt;br /&gt;I guess I would like to emphasize the following point: If you are interested in agile development, you must take the time to &lt;span style="font-style: italic;"&gt;learn&lt;/span&gt;&lt;span style="font-style: italic;"&gt; the value &lt;/span&gt;of the practices you're using. Blindly doing anything will never do any good. However, discomfort I have with notion of "post-agilism" is that the malaise people are experiencing, that's causing them to react, is rooted in fundamental problems: Managers  will read articles about agile and impose it on their teams; so-called gurus will go into a company  dispensing advice without properly understanding what's going on, perhaps without really knowing anything of value in the first place; teams will get caught up in zealous behaviour and start following practices blindly; people will splinter into factions, arguing over minutiae and jealously guarding their particular version of the Truth; incompetence will have its day. Thus dogmatism will set in. The way I see it, these things are inevitable. They are inevitable in the same way that corruption is inevitable in any social or political order. As with corruption, one can only do one's best to manage such problems, to reduce them to a minimum, but one will never get rid of them entirely.&lt;br /&gt;&lt;br /&gt;I fear that creating a new movement/idea and calling it "post-agilism" is just sweeping these basic problems under the rug. If the agile movement is a case of taking some pragmatic ideas and codifying them into a general system, or "going meta" with them, as Bob Martin has &lt;a href="http://weblogs.java.net/blog/rmartin/archive/2003/09/aristotles_erro.html"&gt;written&lt;/a&gt;, then "post-agilism" is a case of going "meta-meta." I can't see how this will lead to any good. Before long, there will be "post-agilist" gurus and dogma, and because of its second order nature, the attendant problems will be much harder to deal with and untangle. I hope that the agile community will get itself out of this spiral and instead will establish ways to do research and to educate people so that as much as possible software development will be about common sense and about what works instead of dogma. Things will never be perfect, but hopefully we can work toward a system that represents the best possible balance and thus minimizes the inevitable corruption that accompanies any human endeavour.&lt;br /&gt;&lt;br /&gt;An agile development process ought to be self-correcting. If that's not working, I'm not sure how embracing "post-agilism" will help:  For better &lt;span style="font-style: italic;"&gt;and&lt;/span&gt; for worse, I think the agile approach represents the best of all possible worlds.&lt;div class="blogger-post-footer"&gt;&lt;img width='1' height='1' src='https://blogger.googleusercontent.com/tracker/10784478-2586261896965335659?l=vladimirlevin.blogspot.com' alt='' /&gt;&lt;/div&gt;</content><link rel='replies' type='application/atom+xml' href='http://vladimirlevin.blogspot.com/feeds/2586261896965335659/comments/default' title='Post Comments'/><link rel='replies' type='text/html' href='http://www.blogger.com/comment.g?blogID=10784478&amp;postID=2586261896965335659' title='7 Comments'/><link rel='edit' type='application/atom+xml' href='http://www.blogger.com/feeds/10784478/posts/default/2586261896965335659'/><link rel='self' type='application/atom+xml' href='http://www.blogger.com/feeds/10784478/posts/default/2586261896965335659'/><link rel='alternate' type='text/html' href='http://vladimirlevin.blogspot.com/2007/04/snake-oil-salesmen-process-skepticism.html' title='Snake-Oil Salesmen, Process Skepticism, and Why I am Not a &quot;Post-Agilist&quot;'/><author><name>Vladimir Levin</name><uri>http://www.blogger.com/profile/09680919094932667147</uri><email>noreply@blogger.com</email><gd:image rel='http://schemas.google.com/g/2005#thumbnail' width='21' height='32' src='http://2.bp.blogspot.com/_zD5Hp0u_Wi0/SqSQJLR_0_I/AAAAAAAAADE/l8j4ET6y63E/S220/vlad_korean.jpg'/></author><thr:total>7</thr:total></entry><entry><id>tag:blogger.com,1999:blog-10784478.post-1891035106286727898</id><published>2007-04-18T15:59:00.000-07:00</published><updated>2007-04-20T08:37:54.800-07:00</updated><title type='text'>TDD: The Bowling Tracker</title><content type='html'>Some years ago I purchased Bob Martin's book &lt;a href="http://www.amazon.com/Software-Development-Principles-Patterns-Practices/dp/0135974445/ref=pd_bbs_sr_1/102-3782738-0507312?ie=UTF8&amp;s=books&amp;amp;qid=1176924175&amp;sr=8-1"&gt;Agile Software Development, Principles, Patterns, and Practices&lt;/a&gt;.  At the start of the book, he brings up a TDD exercise using 10 pin bowling. At the time I thought it would be a good idea to try my hand at the exercise so I avoided reading that chapter in the book; looking at someone else's ready-made solution to a problem tends to create mental blinders so I always try to do things on my own first, then look at the solution in the back, so to speak. Also, if my solution turns out to be inferior, I can learn a lot more from thinking about the differences between the two. I can't remember any more if I ever actually did the exercise or just forgot about it. Recently however, I was thinking about developing this example for potential use in a presentation or seminar about TDD for Eamug. Here then is my implementation along with all of the tests - so feel free to &lt;a href="http://www.geocities.com/vladimir_levin/bowling.html"&gt;have a look&lt;/a&gt;!&lt;br /&gt;&lt;br /&gt;Here are my general observations about the process:&lt;br /&gt;&lt;ul&gt;&lt;li&gt;It took longer than I thought! I expected to spend a couple of hours, but it actually took over a day. I estimate the total development time was about 10 hours!&lt;br /&gt;&lt;/li&gt;&lt;li&gt;Because all of the classes except BowlingLane emerged from refactoring, none of the classes used by BowlingLane had unit tests for their methods. Since none of those methods was public - they were only ever called by BowlingLane which provides the public API, I suppose that's ok. I think my rule is that if a method of a class comes about as a result of refactoring, then there should already be a test for that functionality at a higher level - so one doesn't need to worry about writing a specific test for that method.&lt;/li&gt;&lt;li&gt;Despite the simplicity of the problem, I was surprised to find quite a few gotchas that broke my tests. I definitely think that using TDD to generate this functionality both produced better code and saved time over trying to hack the entire thing out.&lt;br /&gt;&lt;/li&gt;&lt;/ul&gt;PS: Coincidentally Curtis Schofield made a link available to Bob Martin and Robert Koss' &lt;a href="http://www.objectmentor.com/resources/articles/xpepisode.htm"&gt;original bowling TDD example&lt;/a&gt; so feel free to have a look their implementation as well. They focus on just getting the scoring right, so they don't distinguish between an unplayed frame and a scratch where both throws were gutter balls; they also don't seem to handle displaying an empty cumulative score if the player makes a strike or a spare but hasn't made the subsequent throws required to settle the score for the current frame. I suppose that logic could go into display-specific code they didn't bother writing since their emphasis was just on the scoring itself. I might try their approach of just having an array of ints of size 21, which would make the scoring code a lot simpler. Then I'd have to put the smarts around displaying frames properly and displaying an empty cumulative score when appropriate into code that is specific to the display. The nice thing is that now that I have my external API I could in principle completely re-write the back end and as long as I my tests passed, I'd be all right.&lt;br /&gt;&lt;br /&gt;PPS: For bonus marks, I just had a look over my code and I'm pretty sure there is at least one bug! Can you find it? :) Sadly even TDD doesn't remove the possibility of bugs, but I can think of a test that would expose it!&lt;div class="blogger-post-footer"&gt;&lt;img width='1' height='1' src='https://blogger.googleusercontent.com/tracker/10784478-1891035106286727898?l=vladimirlevin.blogspot.com' alt='' /&gt;&lt;/div&gt;</content><link rel='edit' type='application/atom+xml' href='http://www.blogger.com/feeds/10784478/posts/default/1891035106286727898'/><link rel='self' type='application/atom+xml' href='http://www.blogger.com/feeds/10784478/posts/default/1891035106286727898'/><link rel='alternate' type='text/html' href='http://vladimirlevin.blogspot.com/2007/04/tdd-bowling-tracker.html' title='TDD: The Bowling Tracker'/><author><name>Vladimir Levin</name><uri>http://www.blogger.com/profile/09680919094932667147</uri><email>noreply@blogger.com</email><gd:image rel='http://schemas.google.com/g/2005#thumbnail' width='21' height='32' src='http://2.bp.blogspot.com/_zD5Hp0u_Wi0/SqSQJLR_0_I/AAAAAAAAADE/l8j4ET6y63E/S220/vlad_korean.jpg'/></author></entry><entry><id>tag:blogger.com,1999:blog-10784478.post-6597010710354634303</id><published>2007-04-17T21:01:00.000-07:00</published><updated>2007-04-17T21:14:32.378-07:00</updated><title type='text'>EAMUG #2!</title><content type='html'>We had another presentation for Eamug this evening! This time it was about TDD (Test-Driven Development) and Curtis Schofield was the presenter. He did an interesting and decidedly manic presentation and had a very fun presenting style. I think he had a slide at one point that said "Current development practices are teh suck!" or something along those lines, and his presentation was interspersed with random photos of pineapples among other things. It made me feel like I am too didactic when I do presentations - I'm so intent on making sure I am expressing myself clearly that I sometimes forget to just enjoy and have fun and that's a good lesson for me in any future presentations I do. We'll see if I can actually learn that lesson! The only problem I had with the presentation is that the code he was demonstrating - writing a templating engine in ruby - was too sophisticated for a short presentation. Not only was everything in Ruby which was the least well-known language among the attendees but it was ruby on steroids, full of crazy dynamic reflection meta-programming stuff. I had a lot of trouble following what was going on. On the other hand, I learned about some features of Ruby that I didn't know about, so I guess it wasn't entirely a bad thing. It's always tough when you're trying to use an example from a real project rather than a toy project - conveying the context becomes difficult. On the other hand toy projects are by definition not representative of real world issues.  I think introducing TDD in a one hour presentation still requires a toy project though because otherwise it's just too difficult to get everything across clearly. In any case, there was a lively discussion afterward and generally a good feeling in the room and I was really happy to be there.&lt;div class="blogger-post-footer"&gt;&lt;img width='1' height='1' src='https://blogger.googleusercontent.com/tracker/10784478-6597010710354634303?l=vladimirlevin.blogspot.com' alt='' /&gt;&lt;/div&gt;</content><link rel='replies' type='application/atom+xml' href='http://vladimirlevin.blogspot.com/feeds/6597010710354634303/comments/default' title='Post Comments'/><link rel='replies' type='text/html' href='http://www.blogger.com/comment.g?blogID=10784478&amp;postID=6597010710354634303' title='0 Comments'/><link rel='edit' type='application/atom+xml' href='http://www.blogger.com/feeds/10784478/posts/default/6597010710354634303'/><link rel='self' type='application/atom+xml' href='http://www.blogger.com/feeds/10784478/posts/default/6597010710354634303'/><link rel='alternate' type='text/html' href='http://vladimirlevin.blogspot.com/2007/04/eamug-2.html' title='EAMUG #2!'/><author><name>Vladimir Levin</name><uri>http://www.blogger.com/profile/09680919094932667147</uri><email>noreply@blogger.com</email><gd:image rel='http://schemas.google.com/g/2005#thumbnail' width='21' height='32' src='http://2.bp.blogspot.com/_zD5Hp0u_Wi0/SqSQJLR_0_I/AAAAAAAAADE/l8j4ET6y63E/S220/vlad_korean.jpg'/></author><thr:total>0</thr:total></entry><entry><id>tag:blogger.com,1999:blog-10784478.post-7174853017458869189</id><published>2007-04-02T14:31:00.000-07:00</published><updated>2007-04-09T15:52:29.651-07:00</updated><title type='text'>Zen And The Art of Software Development</title><content type='html'>I don't know who deserves the credit for this thought, but a few years ago I read (or someone might have said to me) that no matter how complex an application becomes, it must nevertheless start with a single line of code. Every application, no matter how sophisticated it may be, starts off as a simple application. I think that's a rather deep statement and worth thinking about. Here's my contribution: If you look a random piece of code, say about 10 lines, from &lt;span style="font-style: italic;"&gt;*any*&lt;/span&gt; application, what you see will look much the same. There may be some kind of looping construct, or assignment, or function calls, or some conditional logic. That's true whether you're looking at a Web app, or video game code, or an operating system kernel! That's why I believe so much in the power of simplicity and of abstraction. No matter how devilishly complex or clever your algorithm may need to be, it can be abstracted away into some kind of function call. As for the code around that algorithm, it's probably going to be good old prosaic application logic. That's why using TDD as a design tool is so valuable. It helps to tackle complexity by thinking about interfaces, not gnarly implementation details. It pushes you to organize your code so it is as orthogonal as possible - so that modules of code can work independently and any combination of ways in which that code is executed will still work properly. If your code is like that, you don't &lt;span style="font-style: italic;"&gt;*need* &lt;/span&gt;to test every possible combination - which is impossible anyway. You can count on things working because you've removed the duplication from your code. That's my rant for today, thanks for reading! :)&lt;div class="blogger-post-footer"&gt;&lt;img width='1' height='1' src='https://blogger.googleusercontent.com/tracker/10784478-7174853017458869189?l=vladimirlevin.blogspot.com' alt='' /&gt;&lt;/div&gt;</content><link rel='replies' type='application/atom+xml' href='http://vladimirlevin.blogspot.com/feeds/7174853017458869189/comments/default' title='Post Comments'/><link rel='replies' type='text/html' href='http://www.blogger.com/comment.g?blogID=10784478&amp;postID=7174853017458869189' title='0 Comments'/><link rel='edit' type='application/atom+xml' href='http://www.blogger.com/feeds/10784478/posts/default/7174853017458869189'/><link rel='self' type='application/atom+xml' href='http://www.blogger.com/feeds/10784478/posts/default/7174853017458869189'/><link rel='alternate' type='text/html' href='http://vladimirlevin.blogspot.com/2007/04/random-thought.html' title='Zen And The Art of Software Development'/><author><name>Vladimir Levin</name><uri>http://www.blogger.com/profile/09680919094932667147</uri><email>noreply@blogger.com</email><gd:image rel='http://schemas.google.com/g/2005#thumbnail' width='21' height='32' src='http://2.bp.blogspot.com/_zD5Hp0u_Wi0/SqSQJLR_0_I/AAAAAAAAADE/l8j4ET6y63E/S220/vlad_korean.jpg'/></author><thr:total>0</thr:total></entry><entry><id>tag:blogger.com,1999:blog-10784478.post-1707440861451784802</id><published>2007-03-31T21:09:00.000-07:00</published><updated>2007-03-31T22:44:55.143-07:00</updated><title type='text'>Renovation Cost Overruns</title><content type='html'>I was listening to CBC radio today and they were talking about renovations. It turns out that the average cost of a renovation in Canada is about $5000 and the average cost overrun is 88%! I don't know about other people out there, but I tend to be somewhat ashamed of the poor track record software projects have - they always seem to be late and over budget and more buggy than one would like. It's kind of comforting to note that ours is not the only industry where such things happen. If I were hiring someone to do a renovation, I'd definitely implement the plan as a Scrum project, getting fresh estimates on a regular basis and tracking progress against the original estimate. I'd also have multiple "releases" i.e. I'd make sure one job was competed in its entirety before I agreed to go ahead with the next one.&lt;div class="blogger-post-footer"&gt;&lt;img width='1' height='1' src='https://blogger.googleusercontent.com/tracker/10784478-1707440861451784802?l=vladimirlevin.blogspot.com' alt='' /&gt;&lt;/div&gt;</content><link rel='replies' type='application/atom+xml' href='http://vladimirlevin.blogspot.com/feeds/1707440861451784802/comments/default' title='Post Comments'/><link rel='replies' type='text/html' href='http://www.blogger.com/comment.g?blogID=10784478&amp;postID=1707440861451784802' title='0 Comments'/><link rel='edit' type='application/atom+xml' href='http://www.blogger.com/feeds/10784478/posts/default/1707440861451784802'/><link rel='self' type='application/atom+xml' href='http://www.blogger.com/feeds/10784478/posts/default/1707440861451784802'/><link rel='alternate' type='text/html' href='http://vladimirlevin.blogspot.com/2007/03/renovation-cost-overruns.html' title='Renovation Cost Overruns'/><author><name>Vladimir Levin</name><uri>http://www.blogger.com/profile/09680919094932667147</uri><email>noreply@blogger.com</email><gd:image rel='http://schemas.google.com/g/2005#thumbnail' width='21' height='32' src='http://2.bp.blogspot.com/_zD5Hp0u_Wi0/SqSQJLR_0_I/AAAAAAAAADE/l8j4ET6y63E/S220/vlad_korean.jpg'/></author><thr:total>0</thr:total></entry><entry><id>tag:blogger.com,1999:blog-10784478.post-2585554971324409372</id><published>2007-03-26T09:18:00.000-07:00</published><updated>2007-03-26T09:35:51.554-07:00</updated><title type='text'>Costing A Project Using Scrum and XP</title><content type='html'>&lt;p&gt;At the last &lt;a href="http://groups.google.com/group/eamug"&gt;EAMUG&lt;/a&gt; meeting Mike Boroditsky came up with some good questions about doing an initial costing of a project. Let's say a potential customer comes along and asks you how much she would have to pay for a piece of software she has in mind. How does one go about providing such an estimate in an agile context? If agile software is about iterations and feedback, is there any way to give a customer an up-font estimate? The idea in XP is that every project balances 4 principal variables: Time, Cost, Scope, and Quality. XP fixes the time, cost, and quality. Therefore only scope can be varied during the project. Based on an initial estimate, the developer will commit to a particular schedule, but both the developer and customer must be flexible with respect to scope - the nature of the work that ends up being done. See &lt;a href="http://kw-agiledevelopment.blogspot.com/2007/03/how-can-i-be-sure-my-agile-project-will.html"&gt;here&lt;/a&gt; for a nice elaboration. I think the reality in agile projects is that the time dimension can also stretch as long as the customer is involved in managing the schedule.&lt;br /&gt;&lt;/p&gt;&lt;p&gt;Here's how it might work in context of Scrum/XP: The project starts up  with one (or perhaps several) initial meetings. In these meetings the developer and the customer get together and build up a product backlog. The product backlog is essentially a list of features sorted in order of descending priority. During this process, the developer and customer work together to establish a shared understanding of what the customer is trying to accomplish. Once an initial product backlog has been created, the developer goes over each item in the backlog and provides an estimate. Since each item in the product backlog may expand into multiple stories when it's tackled as part of a sprint, such estimates as not as reliable as etimates for stories. Nevertheless, one should be able to generate reasonable estimates based on how long similar features took on past projects and on a sense of the complexity of given items. Once these estimates are added up, one can tally them up and provide a total time estimate for the&lt;br /&gt;customer. These estimates will be tested against reality in the very first iteration; the burndown chart will make progress clearly visible to all. If progress is totally off-pace from the initial estimate, then that triggers an immediate signal that something is wrong.&lt;br /&gt;&lt;/p&gt;&lt;p&gt;How about fudge factors? I've heard people say they expect some estimates to be too high and others to be too low so that the average should work out to be about right. My experience suggests that estimates are far more likely to be too low than too high. Therefore it may be a good idea to apply a fudge factor to the project. In an agile context where everything is out in the open, it would be important to share this information with the customer. The developer may say to the customer, "the estimates in the product backlog suggest this project will take 3 months to develop but it's very easy for such estimates to be off  by as much as a factor of 2. Let's budget for up  to 6 months." Note however that the estimates are not being inflated -  the budget is being adjusted as a matter of risk management but the estimates are not being changed at all.&lt;br /&gt;&lt;/p&gt;&lt;p&gt;Watching the burndown chart (which is a visual representation of velocity), one can quickly develop a sense of  whether the project is on track. After each iteration, the customer can re-prioritize, add, and remove items. All changes are put back into the product backlog and the developer re-estimates all the items after every iteration. The "red line" allows the customer to clearly see what low priority items are falling out of scope. In an agile environment, the customer is not expected to be able to come up with perfect requirements up front. The customer is allowed to learn more about what she wants as the project goes on and as she is able to interact with the actual working application. The developer is also not expected to understand the requirements perfectly. It is assumed that the developer will misunderstand some requirements such that the application will need to be refined. It's a process of give and take - but again, the overall success of each iteration is assessed by the customer.&lt;br /&gt;&lt;/p&gt;&lt;p&gt;What about quality of estimates? The more familiar a developer is with  a given type of requirement - the domain as well as the technology - and with a particular client, the better the estimate. If you've worked with a client before on a similar project, your estimates are going to be much more accurate. The higher the estimate, the more likely it is to be innacurate. If you think something will take 1 day,  it may take a bit longer. If you think something will take a month, it becomes difficult to understand where that number is coming from. Therefore I suggest that the largest estimate for any given item on a product backlog be one week. If you think something will take more  than a week, then you should find a way to break that requirement up into smaller pieces. It's important to realize anything that will require research is highly uncertain and should be approached with care.&lt;br /&gt;&lt;/p&gt;&lt;p&gt;I think the value of this approach is that it lets the customer see progress very clearly.  After every iteration, the customer gets new features as part of a working application. Also, if the customer is unhappy with the progress being made, every iteration is an opportunity to change things, or in the extreme case to cancel the project before it becomes too expensive.  Importantly. the developer does have the tools to provide an up-front estimate of time and money for a project.&lt;br /&gt;&lt;/p&gt;&lt;div class="blogger-post-footer"&gt;&lt;img width='1' height='1' src='https://blogger.googleusercontent.com/tracker/10784478-2585554971324409372?l=vladimirlevin.blogspot.com' alt='' /&gt;&lt;/div&gt;</content><link rel='replies' type='application/atom+xml' href='http://vladimirlevin.blogspot.com/feeds/2585554971324409372/comments/default' title='Post Comments'/><link rel='replies' type='text/html' href='http://www.blogger.com/comment.g?blogID=10784478&amp;postID=2585554971324409372' title='4 Comments'/><link rel='edit' type='application/atom+xml' href='http://www.blogger.com/feeds/10784478/posts/default/2585554971324409372'/><link rel='self' type='application/atom+xml' href='http://www.blogger.com/feeds/10784478/posts/default/2585554971324409372'/><link rel='alternate' type='text/html' href='http://vladimirlevin.blogspot.com/2007/03/costing-project-using-scrum.html' title='Costing A Project Using Scrum and XP'/><author><name>Vladimir Levin</name><uri>http://www.blogger.com/profile/09680919094932667147</uri><email>noreply@blogger.com</email><gd:image rel='http://schemas.google.com/g/2005#thumbnail' width='21' height='32' src='http://2.bp.blogspot.com/_zD5Hp0u_Wi0/SqSQJLR_0_I/AAAAAAAAADE/l8j4ET6y63E/S220/vlad_korean.jpg'/></author><thr:total>4</thr:total></entry><entry><id>tag:blogger.com,1999:blog-10784478.post-8771199260576946196</id><published>2007-03-26T09:12:00.000-07:00</published><updated>2007-04-01T07:08:08.896-07:00</updated><title type='text'>EAMUG</title><content type='html'>I've started an agile group here in Edmonton, &lt;a href="http://groups.google.com/group/eamug"&gt;EAMUG&lt;/a&gt; - or Edmonton Agile Methods Users Group! So far I've met some good people and I presented at our first meeting, which I think went pretty well. Rod Potter, who works at IBM, made a fantastic room available for us at their innovation centre. I hope we'll have more good meetings in the future!&lt;div class="blogger-post-footer"&gt;&lt;img width='1' height='1' src='https://blogger.googleusercontent.com/tracker/10784478-8771199260576946196?l=vladimirlevin.blogspot.com' alt='' /&gt;&lt;/div&gt;</content><link rel='replies' type='application/atom+xml' href='http://vladimirlevin.blogspot.com/feeds/8771199260576946196/comments/default' title='Post Comments'/><link rel='replies' type='text/html' href='http://www.blogger.com/comment.g?blogID=10784478&amp;postID=8771199260576946196' title='1 Comments'/><link rel='edit' type='application/atom+xml' href='http://www.blogger.com/feeds/10784478/posts/default/8771199260576946196'/><link rel='self' type='application/atom+xml' href='http://www.blogger.com/feeds/10784478/posts/default/8771199260576946196'/><link rel='alternate' type='text/html' href='http://vladimirlevin.blogspot.com/2007/03/eamug.html' title='EAMUG'/><author><name>Vladimir Levin</name><uri>http://www.blogger.com/profile/09680919094932667147</uri><email>noreply@blogger.com</email><gd:image rel='http://schemas.google.com/g/2005#thumbnail' width='21' height='32' src='http://2.bp.blogspot.com/_zD5Hp0u_Wi0/SqSQJLR_0_I/AAAAAAAAADE/l8j4ET6y63E/S220/vlad_korean.jpg'/></author><thr:total>1</thr:total></entry><entry><id>tag:blogger.com,1999:blog-10784478.post-5489545962999698949</id><published>2007-03-22T11:37:00.000-07:00</published><updated>2007-03-22T11:41:19.388-07:00</updated><title type='text'>Orcs And Elves</title><content type='html'>From &lt;a href="http://www.armadilloaerospace.com/n.x/johnc/Recent%20Updates"&gt;John Carmack's blog&lt;/a&gt;:&lt;br /&gt;&lt;blockquote&gt;O&amp;amp;E development was started high-end first with the low-end versions done afterwards.  I should have known better (Anna was certainly suspicious), because it is always easier to add flashy features without introducing any negatives than it is to chop things out without damaging the core value of a game. &lt;br /&gt;&lt;/blockquote&gt;I think this is true of all development, not just games, and it's why adding a lot of flashy stuff up-front is a bad idea. Unfortunately, users often are much more impressed with the bells and whistles than with core functionality. Striking the right balance is one of the hardest things about software development. Agile approaches emphasize a vertical style of development - get it working end to end, then add more advanced capabilities, but it's often hard to do that with users often demanding cosmetic features that are not necessarily easy to implement and impose a debt load for ongoing development.&lt;div class="blogger-post-footer"&gt;&lt;img width='1' height='1' src='https://blogger.googleusercontent.com/tracker/10784478-5489545962999698949?l=vladimirlevin.blogspot.com' alt='' /&gt;&lt;/div&gt;</content><link rel='replies' type='application/atom+xml' href='http://vladimirlevin.blogspot.com/feeds/5489545962999698949/comments/default' title='Post Comments'/><link rel='replies' type='text/html' href='http://www.blogger.com/comment.g?blogID=10784478&amp;postID=5489545962999698949' title='0 Comments'/><link rel='edit' type='application/atom+xml' href='http://www.blogger.com/feeds/10784478/posts/default/5489545962999698949'/><link rel='self' type='application/atom+xml' href='http://www.blogger.com/feeds/10784478/posts/default/5489545962999698949'/><link rel='alternate' type='text/html' href='http://vladimirlevin.blogspot.com/2007/03/orcs-and-elves.html' title='Orcs And Elves'/><author><name>Vladimir Levin</name><uri>http://www.blogger.com/profile/09680919094932667147</uri><email>noreply@blogger.com</email><gd:image rel='http://schemas.google.com/g/2005#thumbnail' width='21' height='32' src='http://2.bp.blogspot.com/_zD5Hp0u_Wi0/SqSQJLR_0_I/AAAAAAAAADE/l8j4ET6y63E/S220/vlad_korean.jpg'/></author><thr:total>0</thr:total></entry><entry><id>tag:blogger.com,1999:blog-10784478.post-211346963879778213</id><published>2007-03-07T08:48:00.000-08:00</published><updated>2007-03-12T10:56:56.642-07:00</updated><title type='text'>What Is a Successful Project?</title><content type='html'>What Is a Successful Project?&lt;br /&gt;&lt;br /&gt;A few years ago I would have promptly answered that a successful project is on time, on budget, and does what the customer intended it to do. Over the course of the last few years though, I've learned that things aren't quite so simple. Developing software is a human activity and it's taken me a while to figure out that 'success' is a profoundly subjective notion.&lt;br /&gt;&lt;br /&gt;Let's say youre a painter and you've been hired to paint a house. You go in, do the job, and when the customers look at what you've done, all you hear are complaints:  They can see a few rivulets of paint near the ceiling, the paint job is not &lt;span style="font-style: italic;"&gt;perfectly&lt;/span&gt; even everywhere, etc... The fact is that there's no such thing a s a perfect paint job so it's up to the customer and the painter to come to an understanding of what's reasonable and what's not. Trying to settle the matter confrontationally is unpleasant for both sides and should only be a measure of last resort. The same is true in software, only more so. The degree of sophistication to which any given requirement can be implemented can vary enormously and it's important to come to a general understanding with a customer about what is expected and how much time and money will be involved. As a simple example, let's consider Web form validation. A simple way to validate data entered on a Web site is to have the application issue error messages that are displayed when a form is submitted. However, in addition to this basic type of validation, the customer may want validation to occur 'live' as the user is filling in fields on a form - in practice this rquires either client-side validation with Javascript or asynchronous server calls using 'ajax'. The customer may also want automatic filtering on fields to prevent the user from entering incorrect data - a typical case in point is filtering provinces/states once a country has been selected, and then additionally filtering cities once a province/state has been selected. Depending on what the customer really wants, a story may simply state the validation rules for a given form or it may describe these kinds of things in detail. In the first case, XP would indicate the simplest approach applies and the customer would have to draft a subsequent story to enhance validation. In the second case, fancy validation would have to be considered a &lt;span style="font-style: italic;"&gt;motherhood story&lt;/span&gt; - something that is an essential part of the application right from the start and cuts across all stories (other examples of typical motherhood stories include Security, Performance, Failover, etc.). Thus, the Fancy Validation motherhood story would be an aspect of development for every form and support for it would have to be built into the code framework fairly early on. Every development activity can be approached horizonally or vertically. Implementing fancy validation right away across the board would be an example of a horizontal approach. The vertical approach would suggest getting substantial parts of the application working satisfactorily before contemplating such niceties. Agile development tends to emphasize a vertical (get it working end to end first) approach, but it's essential to pay attention to the customer.  Perhaps the customer can be convinced to alter priorities; on the other hand, the customer may know exactly what he or she wants and having raised the matter and given appropriate feedback with respect to risk and cost, etc, it would be the developer's job to carry out the customer's instructions.&lt;br /&gt;&lt;br /&gt;In the previous paragraph I was trying to describe the kind of situation where the developer may think that everything is ok but the customer isn't happy. It's even possible the customer is being unreasonable but the bottom line is that a project where the customer is not happy cannot be a success, even if it appears to meet the stated requirements and is also on time and on budget. Now let's suppose the developer and the customer meet to discuss a new project. The developer provides an estimate of 6 months. 2 months into the project, the developer shows the customer the burndown chart which clearly indicates, given the progress made so far, that the project is much more likely to take about a year. There could be many reasons for this to happen. Perhaps as per the earlier discussion, the customer wants features to be implemented in a more sophisticated way than anticipated. In any case, the customer decides that despite the delay, the project is worth continuing. At the end of  a year the project is delivered to, and accepted by, the customer. On one hand this project has exceeded its initial estimate by 100%! On the other hand the customer made the decision to continue and is satisfied with the result. It's probably reasonable to suggest that this project is a success, in spite of the budget overrun.&lt;br /&gt;&lt;br /&gt;While being on time and on budget is important, and it's also important to satisfy the stated requirements for a project, the reality of software development is that constant communication is essential. Ultimately only the customer and the developer can together decide whether a project should be deemed a success or a failure. There doesn't exist any infallible objective measure of success. If you ignore customer expectations, you may end up delivering something on time and on budget that the users aren't happy with, and then you'll spend a huge amount of time arguing over whose fault it all was - was development not getting the requirements right or was the customer not being specific enough: The kind of confrtonational quagmire one often runs into in waterfall-ish projects. Agile software development provides the tools to resolve these problems, but both the customer and developer sides need to put in the work to strike the right balance between "lots of cool bells and whistles" and "a lean, focused, no-frills piece of software that does what it's supposed to do." It's also a good idea to always think about the difference between the horizontal and vertical styles of development. Some features are best implemented horizontally and others vertically. In an agile development context such decisions ought to considered frequently and reviewed often. I hope this helps you to make your next project a success - whatever that means!&lt;div class="blogger-post-footer"&gt;&lt;img width='1' height='1' src='https://blogger.googleusercontent.com/tracker/10784478-211346963879778213?l=vladimirlevin.blogspot.com' alt='' /&gt;&lt;/div&gt;</content><link rel='replies' type='application/atom+xml' href='http://vladimirlevin.blogspot.com/feeds/211346963879778213/comments/default' title='Post Comments'/><link rel='replies' type='text/html' href='http://www.blogger.com/comment.g?blogID=10784478&amp;postID=211346963879778213' title='2 Comments'/><link rel='edit' type='application/atom+xml' href='http://www.blogger.com/feeds/10784478/posts/default/211346963879778213'/><link rel='self' type='application/atom+xml' href='http://www.blogger.com/feeds/10784478/posts/default/211346963879778213'/><link rel='alternate' type='text/html' href='http://vladimirlevin.blogspot.com/2007/03/what-is-successful-project.html' title='What Is a Successful Project?'/><author><name>Vladimir Levin</name><uri>http://www.blogger.com/profile/09680919094932667147</uri><email>noreply@blogger.com</email><gd:image rel='http://schemas.google.com/g/2005#thumbnail' width='21' height='32' src='http://2.bp.blogspot.com/_zD5Hp0u_Wi0/SqSQJLR_0_I/AAAAAAAAADE/l8j4ET6y63E/S220/vlad_korean.jpg'/></author><thr:total>2</thr:total></entry><entry><id>tag:blogger.com,1999:blog-10784478.post-4218313283356685640</id><published>2006-12-01T09:26:00.000-08:00</published><updated>2006-12-17T18:28:44.908-08:00</updated><title type='text'>Notable Books</title><content type='html'>There are so many books about software development out there. Here is my list of essentials:&lt;br /&gt;&lt;ul&gt;&lt;li&gt;&lt;a href="http://www.amazon.com/Code-Complete-Second-Steve-McConnell/dp/0735619670/sr=1-1/qid=1164995348/ref=pd_bbs_sr_1/103-3844764-8506231?ie=UTF8&amp;s=books"&gt;Code Complete&lt;/a&gt;: This book is a classic, and the new edition covers a lot of new material. I would suggest that thoroughly going over this book would be an excellent preparation for professional software development, and would put one ahead of most of the people already out there working in the industry. Steve Mcconnell has that great quality of explaining things clearly without needless embellishment.&lt;/li&gt;&lt;li&gt;&lt;a href="http://www.amazon.com/Agile-Software-Development-SCRUM-Schwaber/dp/0130676349/sr=8-2/qid=1166320456/ref=pd_bbs_sr_2/102-5053295-1728950?ie=UTF8&amp;amp;s=books"&gt;Agile Software Development with SCRUM&lt;/a&gt;:  Scrum provides a very simple and lightweight set of project management artifacts, yet these few simple lists and charts produce a powerful form of feedback. Scrum also enlists all stakeholders in a software project to be honest and courageous, and to keep everything out in the open. It is my preferred method of managing software development.&lt;br /&gt;&lt;/li&gt;&lt;li&gt;&lt;a href="http://www.amazon.com/Fundamentals-Object-Oriented-Design-Meilir-Page-Jones/dp/020169946X/sr=1-1/qid=1164995415/ref=sr_1_1/103-3844764-8506231?ie=UTF8&amp;s=books"&gt;Fundamentals of Object-Oriented Design in UML&lt;/a&gt;: For anyone who wants to understand object-oriented programming more deeply, in terms of the true underlying principles, I think this book is a great choice. It make you think about design patterns in a more profound way. The use of the word "fundamentals" in the title has more to do with the notion of depth and first principles; it's not necessarily a book for novices. I think this is one of the most underrated books in software development. There's an intro to UML too, to me, that's hardly the main point of this terrific book.&lt;br /&gt;&lt;/li&gt;&lt;li&gt;&lt;a href="http://www.amazon.com/Rapid-Development-Steve-McConnell/dp/1556159005/sr=1-2/qid=1164995348/ref=pd_bbs_2/103-3844764-8506231?ie=UTF8&amp;s=books"&gt;Rapid Development&lt;/a&gt;: Another Steve Mcconnell book. What he did for programming in Code Complete, here he extends to management of software projects. This book is very well researched and comprehensive.&lt;br /&gt;&lt;/li&gt;&lt;li&gt;&lt;a href="http://www.amazon.com/Extreme-Programming-Explained-Embrace-Change/dp/0321278658/sr=1-1/qid=1164995440/ref=pd_bbs_sr_1/103-3844764-8506231?ie=UTF8&amp;amp;s=books"&gt;XP Explained&lt;/a&gt;: Kent Beck expounds his XP philosophy. Test-driven development, or TDD, fundamentally changed my approach to programming. I don't think you have to practice XP to have a successful software project, but I do believe that the general attitude of XP when it is applied correctly is the right one.&lt;br /&gt;&lt;/li&gt;&lt;li&gt;&lt;a href="http://www.amazon.com/Refactoring-Improving-Design-Existing-Code/dp/0201485672/sr=1-1/qid=1164995463/ref=pd_bbs_sr_1/103-3844764-8506231?ie=UTF8&amp;s=books"&gt;Refactoring&lt;/a&gt;: While this book is rather wordy for its content, it's worth reading. The most important idea in this book is that you don't have to produce a glorious design on paper before writing any code but instead you can incrementally shape your code as you go on. However, it is also important to realize that thinking hard about one's design is a very important part of the test-code-refactor cycle: It's not just about moving code around.&lt;br /&gt;&lt;/li&gt;&lt;li&gt;&lt;a href="http://www.amazon.com/Design-Patterns-Object-Oriented-Addison-Wesley-Professional/dp/0201633612/sr=1-1/qid=1164995489/ref=pd_bbs_sr_1/103-3844764-8506231?ie=UTF8&amp;amp;s=books"&gt;Design Patterns&lt;/a&gt;: In my opinion this is a somewhat overrated book. It's really an exploration of  techniques that polymorphism (overriding functions via inheritance) makes possible. In that respect it's certainly worth reading, but it has spawned a cult of object/pattern nonsense who's nefarious influence continues to make itself felt to this day.&lt;br /&gt;&lt;/li&gt;&lt;/ul&gt;&lt;div class="blogger-post-footer"&gt;&lt;img width='1' height='1' src='https://blogger.googleusercontent.com/tracker/10784478-4218313283356685640?l=vladimirlevin.blogspot.com' alt='' /&gt;&lt;/div&gt;</content><link rel='replies' type='application/atom+xml' href='http://vladimirlevin.blogspot.com/feeds/4218313283356685640/comments/default' title='Post Comments'/><link rel='replies' type='text/html' href='http://www.blogger.com/comment.g?blogID=10784478&amp;postID=4218313283356685640' title='2 Comments'/><link rel='edit' type='application/atom+xml' href='http://www.blogger.com/feeds/10784478/posts/default/4218313283356685640'/><link rel='self' type='application/atom+xml' href='http://www.blogger.com/feeds/10784478/posts/default/4218313283356685640'/><link rel='alternate' type='text/html' href='http://vladimirlevin.blogspot.com/2006/12/notable-books.html' title='Notable Books'/><author><name>Vladimir Levin</name><uri>http://www.blogger.com/profile/09680919094932667147</uri><email>noreply@blogger.com</email><gd:image rel='http://schemas.google.com/g/2005#thumbnail' width='21' height='32' src='http://2.bp.blogspot.com/_zD5Hp0u_Wi0/SqSQJLR_0_I/AAAAAAAAADE/l8j4ET6y63E/S220/vlad_korean.jpg'/></author><thr:total>2</thr:total></entry><entry><id>tag:blogger.com,1999:blog-10784478.post-7801999900085036035</id><published>2006-11-11T11:43:00.002-08:00</published><updated>2006-11-11T12:17:10.720-08:00</updated><title type='text'>Mock Objects and Testing</title><content type='html'>I have heard rumblings of controversy around testing with mock objects. For example, &lt;a href="http://www.jeffperrin.com/"&gt;Jeff Perrin&lt;/a&gt;  had an interesting link in his blog to an article about &lt;a href="http://homepage.mac.com/keithray/blog/2006/10/31/"&gt;why not to use mock objects&lt;/a&gt;. I find it hard when I'm trying to illustrate an idea to come up with simple examples off the top of my head. They tend to be either very specific to a project I'm working on or very contrived. That's why I figured I would take an opportunity to describe something simple yet concrete that I encountered the other day at work. In the project I'm currently working on, I was trying to fix a bug. To do so, I added a condition to a function that retrieved a list of wells. This function was retrieving all of the wells connected to a given battery (effectively a storage tank for oil produced at a well). I modified the function to return only wells that had not been "shut-in." While running all of our tests, I ran across a few tests that were breaking as a result of my change. The tests had to do with contracts, an area of the system I am not very familiar with. I asked one of our on-site business users about this and it turned out that it made sense in certain circumstances to include as part of processing a contract wells that were shut-in.&lt;br /&gt;&lt;br /&gt;I thought this was interesting because the tests we had did not use mock objects. Because of this I was able to see failures resulting as part of my change in tests that had real business meaning which explained to me why my change was not a good idea. With mock obects, I imagine the tests would have been decoupled. There would be tests for the function that returned wells at a battery. Then there would be tests to make sure contracts were being processed correctly. These latter tests would mock or stub out the function that searched for wells at a battery. Therefore the change I made would only have likely broken one test that made sure that particulr function included shut-in wells, outside of any other context. On one hand that seems like a good thing but the problem is, without having the context of the business problems in which shut-in wells should be included, I could imagine thinking the failing test was probably wrong.&lt;br /&gt;&lt;br /&gt;One could argue first of all that's what the on-site customer is for in XP, and secondly that one should also have customer facing integration tests (FIT tests) that would probably fail as a result of this type of change. Still, in the first case the customers were busy and may not have thought of the problem the failing contract test had identified, at least not right on the spot. As for the integration tests, by definition these would probably be run as a batch job overnight so I wouldn't find out about the problem I had checked into source control until quite a bit later on.&lt;br /&gt;&lt;br /&gt;It's this sort of thinking that leads me to believe that over-mocking is a bad idea. If a test is triggering code that accesses external resources that a) are not available at the time the test is being run or b) the test takes too long to run, or c) the application code does not yield consistent results over time (as in the case of a stock-ticker or a system clock), that test is a good candidate for using stubs or mocks. Otherwise I think it's best to avoid mocking or stubbing as a matter of principle.&lt;div class="blogger-post-footer"&gt;&lt;img width='1' height='1' src='https://blogger.googleusercontent.com/tracker/10784478-7801999900085036035?l=vladimirlevin.blogspot.com' alt='' /&gt;&lt;/div&gt;</content><link rel='replies' type='application/atom+xml' href='http://vladimirlevin.blogspot.com/feeds/7801999900085036035/comments/default' title='Post Comments'/><link rel='replies' type='text/html' href='http://www.blogger.com/comment.g?blogID=10784478&amp;postID=7801999900085036035' title='0 Comments'/><link rel='edit' type='application/atom+xml' href='http://www.blogger.com/feeds/10784478/posts/default/7801999900085036035'/><link rel='self' type='application/atom+xml' href='http://www.blogger.com/feeds/10784478/posts/default/7801999900085036035'/><link rel='alternate' type='text/html' href='http://vladimirlevin.blogspot.com/2006/11/mock-objects-and-testing_2866.html' title='Mock Objects and Testing'/><author><name>Vladimir Levin</name><uri>http://www.blogger.com/profile/09680919094932667147</uri><email>noreply@blogger.com</email><gd:image rel='http://schemas.google.com/g/2005#thumbnail' width='21' height='32' src='http://2.bp.blogspot.com/_zD5Hp0u_Wi0/SqSQJLR_0_I/AAAAAAAAADE/l8j4ET6y63E/S220/vlad_korean.jpg'/></author><thr:total>0</thr:total></entry><entry><id>tag:blogger.com,1999:blog-10784478.post-116058681315733042</id><published>2006-10-11T10:01:00.000-07:00</published><updated>2006-10-24T05:33:54.016-07:00</updated><title type='text'>Command Pattern</title><content type='html'>Jeff wrote commenting about one of my posts on validation:&lt;br /&gt;&lt;br /&gt;&lt;blockquote&gt;I also like the idea of just having an isValid() method type solution. I did a 1 day spike on our Well class to look at implementing our validation as separate business rule objects. This way, you can easily validate based on a given context, so you could have different rules be applicable during creation vs during an update (as an example).&lt;br /&gt;&lt;br /&gt;I was particulary inspired by this post:&lt;br /&gt;http://www.jpboodhoo.com/blog/ValidationInTheDomainLayerTakeOne.aspx&lt;/blockquote&gt;This comment made me think about the command pattern and its applicability to different problems. The basic idea of the command pattern is to convert a function into a full-blown class. You can read more about it &lt;a href="http://en.wikipedia.org/wiki/Command_pattern"&gt;here&lt;/a&gt; on wikipedia. I've used the command pattern in a number of projects in the past. Here are a couple of examples: On one of my projects, users were able to choose from a number of batch processes they wanted to run, either to load data or to do diagnostics on large recordsets all at once. In general there were several hundred thousand records processed by each such batch job. Another developer started off by writing code that implemented each process as a function in a large class. This was an oil and gas application, so he had functions like loadWells(), loadPools(), etc... all in one class. There was a lot of duplication from one function to another and the code was messy, so one of the first things I did was to refactor it into the command pattern. I turned each loading process into a class that implemented a single method, execute. For example, I had a WellLoader class, and a PoolLoader class that both extended a BatchProcess abstract base class which exposed an abstract execute method. The base class also exposed some protected methods that permitted, among other things, a progress indicator during batch processing (since each batch job generally took several hours). When users selected which batch processes they wanted to run, the system would create an instance of each job and add them all to a list, then successively called the execute method on each one. Whatever the details of implementation of each batch process, its only public interface consisted of the methods in the BatchProcess class, primarily the execute method. Another case where I used the command pattern was an embedded system in the scada world that did scheduled polling of sensors. In this case I took advantage of the command pattern to schedule and execute different kinds of polls and alarms. I set up each poll or alarm one as a different class. The scheduler class would loop through each process in its queue and if it was time to run that process, it would call its send method.&lt;br /&gt;&lt;br /&gt;In &lt;a href="http://domaindrivendesign.org/books/index.html#DDD"&gt;Domain Driven Design&lt;/a&gt;, Eric Evans shows how the command pattern can be used to create specification objects. Such objects can be chained together to validate constraints, create objects,  or filter lists. I think the example Jeff presents above falls into this general category. It's an interesting idea, but I think some caution is warranted, because the goal of patterns is to simplify code and reduce duplication. If validation rules can re-used or need to be chained together and executed in different combinations at different times, then it makes sense to use the command pattern. However, if validation rules are always applicable to a given domain object and are not re-used between different classes, then maybe the less flashy approach of just making each validation a method in a Validator class is more readable and good enough.&lt;br /&gt;&lt;br /&gt;On a quick final note, I recently read Jamie Mcilroy's post about &lt;a href="http://jamiemcilroy.wordpress.com/2006/10/10/not-quite-what-i-expectedjsf-validation/"&gt;JSF validation&lt;/a&gt;. It seems as though JSF binds the gui directly to a domain object and invokes validation separately for each form field. I don't know how much I like that. I think I'd rather JSF invoked validation on the whole domain object in one call and used keys to determine which form fields had errors. Anyway, given the way it seems to work, that might be a good opportunity to take advantage of Jeff's idea of making each validation a separate class. That way, each attribute validation can easily be invoked from JSF but still be indepedent from the JSF framework itself.&lt;div class="blogger-post-footer"&gt;&lt;img width='1' height='1' src='https://blogger.googleusercontent.com/tracker/10784478-116058681315733042?l=vladimirlevin.blogspot.com' alt='' /&gt;&lt;/div&gt;</content><link rel='replies' type='application/atom+xml' href='http://vladimirlevin.blogspot.com/feeds/116058681315733042/comments/default' title='Post Comments'/><link rel='replies' type='text/html' href='http://www.blogger.com/comment.g?blogID=10784478&amp;postID=116058681315733042' title='3 Comments'/><link rel='edit' type='application/atom+xml' href='http://www.blogger.com/feeds/10784478/posts/default/116058681315733042'/><link rel='self' type='application/atom+xml' href='http://www.blogger.com/feeds/10784478/posts/default/116058681315733042'/><link rel='alternate' type='text/html' href='http://vladimirlevin.blogspot.com/2006/10/command-pattern.html' title='Command Pattern'/><author><name>Vladimir Levin</name><uri>http://www.blogger.com/profile/09680919094932667147</uri><email>noreply@blogger.com</email><gd:image rel='http://schemas.google.com/g/2005#thumbnail' width='21' height='32' src='http://2.bp.blogspot.com/_zD5Hp0u_Wi0/SqSQJLR_0_I/AAAAAAAAADE/l8j4ET6y63E/S220/vlad_korean.jpg'/></author><thr:total>3</thr:total></entry><entry><id>tag:blogger.com,1999:blog-10784478.post-115990975016555703</id><published>2006-10-03T13:49:00.000-07:00</published><updated>2006-10-21T07:41:52.001-07:00</updated><title type='text'>Defensive Programming: Handling Nulls</title><content type='html'>C was one of the first languages I learned to program in. In C, you access memory direcly with pointers and it's not unusual for bugs to arise from improperly dereferencing those pointers. This generally causes the application to crash, often with a segmentation fault or bus error, and sometimes the application manages to carry on, overwriting memory until it finally fails, often in a way that is very difficult to reproduce or track down. Accessing memory directly certainly gives the maximum amount of control, but it's also very error-prone. In managed/interpreted environments, like Java, C#, Perl, Python, or Ruby, one can't access memory directly. Instead, the runtime environment interposes a handle to an object or structure. This prevents most of the memory problems that arise in C applications. However, there is still the problem of using references that don't point to any particular object. These are called null references, or nil references, or something along those lines. In Java, when you call a method on a reference that doesn't point to any object, the runtime throws a NullPointerException. I'd rather it throw something like a NullReferenceException, but that's neither here not there :). It's not nearly as bad as having memory problems in C, because you can trap these exceptions and then your application can carry on, but it doesn't improve user confidence, and it leaves parts of the application inaccessible to the user.&lt;br /&gt;&lt;br /&gt;One of the ways to handle such exceptions is called the Null Object pattern. basically, the idea is to guarantee that a reference to a particular kind of object will always be initialized with a stub that implements some kind of harmless do-nothing behaviour for that type of object. The idea is to guarantee that an object will always be there when you call a method on an object reference. Let's say your application involves keeping track of customers. If you search for a customer with an invalid id, instead of returning null, you'd get back a Customer object. If you try to call any methods on this object, they will either do nothing or return intelligent defaults. For example, getAge() would return 0. This is a useful pattern, but there are some issues to keep in mind. First of all, there will always be cases where one must distinguish between a real object and a null object stub. This is generally done by implementing an isNull method for all domain objects (in Java, you could create a Substitutable interface for this purpose). This isNull method will only return true when executed on Null objects. Secondly, defining the proper do-nothing behaviour for complex domain objects can lead to overhead. In an example below, I will try to show an what might need to be done to rigorously implement Null Object. Also, If you want to use the Null Object pattern, you should adhere to the Law Of Demeter to avoid having to implement a whole bunch of un-necessary Null Object types. In other words, instead of having something like student.findExam(3).getGrade(), you would simply call student.getGradeForExam(3). This approach makes the Student class easier to turn into a Null Object. If you tend to be checking object.isNull all the time, then maybe this pattern is not the right one to use, since it is designed for cases where most of the time, you are ok with the Null Object's default behaviour. Finally, I'm not sure it's possible to always define proper do-nothing behaviour that won't depend on some context, though I can't think of a real case of this problem at the moment.&lt;br /&gt;&lt;br /&gt;Here is an example I've tried to cook up to show what Null object implemented&lt;br /&gt;throughout an application might look like (it's Java code, as usual, since that's&lt;br /&gt;the language I feel most comfortable with). &lt;br /&gt;&lt;pre&gt;&lt;br /&gt; public interface Substitutable {&lt;br /&gt;   public boolean isNull();&lt;br /&gt; }&lt;br /&gt;&lt;br /&gt; public abstract class NullObject implements Substitutable {&lt;br /&gt;   public boolean isNull() {&lt;br /&gt;     return true;&lt;br /&gt;   }&lt;br /&gt;&lt;br /&gt;   public boolean equals() {&lt;br /&gt;     return false;&lt;br /&gt;   }&lt;br /&gt; }&lt;br /&gt;&lt;br /&gt; public abstract class DomainEntity implements Substitutable {&lt;br /&gt;   public boolean isNull() {&lt;br /&gt;     return false;&lt;br /&gt;   }&lt;br /&gt; }&lt;br /&gt;&lt;br /&gt; public interface Customer {&lt;br /&gt;   public String getName();&lt;br /&gt;   public void setName(String name);&lt;br /&gt; }&lt;br /&gt;&lt;br /&gt; public class CustomerImpl extends DomainEntity implements Customer {&lt;br /&gt;   public String getName() {&lt;br /&gt;     return name;&lt;br /&gt;   }&lt;br /&gt;&lt;br /&gt;   public void setName(String aName) {&lt;br /&gt;     name = aName;&lt;br /&gt;   }&lt;br /&gt; }&lt;br /&gt;&lt;br /&gt; public class NullCustomer extends NullObject implements Customer {&lt;br /&gt;   public String getName() {&lt;br /&gt;     return "";&lt;br /&gt;   }&lt;br /&gt;&lt;br /&gt;   public void setName(String s) {}&lt;br /&gt; }&lt;br /&gt;&lt;/pre&gt;&lt;br /&gt;&lt;br /&gt;Note the extra overhead of an interface for each domain class needed (at least in my example) to more easily support NullObject. To introduce methods in Customer that return proper domain entities rather than value objects like String, I'd have to provide NullObject support for those as well! Also, I've implemented default behavour for equals method to always return false. I wonder that the right behaviour for hashCode might be. Hmmm. It's definitely a bit of extra work. Is it worth it? I haven't ever tried this approach so I'm not really sure. &lt;br /&gt;&lt;br /&gt;While the Null Object pattern can be helpful in eliminating null exceptions, it has to be implemtented judiciously throughout an application. Another approach I tend to use to prevent having to check for nulls all over the place, which I haven't seen on too many other projects, is to write static utility methods for many standard operations that compare two objects in some way. For example, one often finds code like if &lt;span style="font-style: italic;"&gt;(a != null and a.equals(b))&lt;/span&gt; - I suggest replacing that with &lt;span style="font-style: italic;"&gt;if (Util.equal(a,b))&lt;/span&gt;. Here is how I implement the Util.equal method:&lt;br /&gt;&lt;pre&gt; public static boolean equal(Object a, Object b) {&lt;br /&gt;if (a == null || b == null)&lt;br /&gt; return false;&lt;br /&gt;return a.equals(b);&lt;br /&gt;}&lt;br /&gt;&lt;/pre&gt;Again, if a were a Null Object, it would implement the equals method by just returning false.&lt;br /&gt;&lt;br /&gt;Other ideas include numeric comparisons on non-primitive numeric types, e.g. &lt;span style="font-style: italic;"&gt;isZero(Number a)&lt;/span&gt;, &lt;span style="font-style: italic;"&gt;isLessThan(Number a, Number b)&lt;/span&gt;, &lt;span style="font-style: italic;"&gt;etc...&lt;/span&gt;, date comparisons, and so on.&lt;div class="blogger-post-footer"&gt;&lt;img width='1' height='1' src='https://blogger.googleusercontent.com/tracker/10784478-115990975016555703?l=vladimirlevin.blogspot.com' alt='' /&gt;&lt;/div&gt;</content><link rel='replies' type='application/atom+xml' href='http://vladimirlevin.blogspot.com/feeds/115990975016555703/comments/default' title='Post Comments'/><link rel='replies' type='text/html' href='http://www.blogger.com/comment.g?blogID=10784478&amp;postID=115990975016555703' title='0 Comments'/><link rel='edit' type='application/atom+xml' href='http://www.blogger.com/feeds/10784478/posts/default/115990975016555703'/><link rel='self' type='application/atom+xml' href='http://www.blogger.com/feeds/10784478/posts/default/115990975016555703'/><link rel='alternate' type='text/html' href='http://vladimirlevin.blogspot.com/2006/10/defensive-programming-handling-nulls.html' title='Defensive Programming: Handling Nulls'/><author><name>Vladimir Levin</name><uri>http://www.blogger.com/profile/09680919094932667147</uri><email>noreply@blogger.com</email><gd:image rel='http://schemas.google.com/g/2005#thumbnail' width='21' height='32' src='http://2.bp.blogspot.com/_zD5Hp0u_Wi0/SqSQJLR_0_I/AAAAAAAAADE/l8j4ET6y63E/S220/vlad_korean.jpg'/></author><thr:total>0</thr:total></entry><entry><id>tag:blogger.com,1999:blog-10784478.post-115962512117656047</id><published>2006-09-30T06:31:00.000-07:00</published><updated>2006-10-21T07:41:51.947-07:00</updated><title type='text'>Validation IV</title><content type='html'>I figured I would write a bit more about validation after my last three already long winded posts on the subject. Basically this is just a brief synopsis with an example and a few minor elaborations.  My major conclusion is that all domain-level validation that one would think to put into setting methods or initializers/constructors should instead be done via a single method for each domain object. Let's call that method valid, or isValid, or validate. Ideally, rather than throwing an exception every time it finds an error, this method would add messages as it goes along, and would only throw an exception when it's done. In Java, here's a typical example:&lt;br /&gt;&lt;pre&gt;&lt;span style=";font-family:courier new;font-size:85%;"  &gt;public void validate() throws ValidationException {&lt;br /&gt;Messages messages = new Messages(this);&lt;br /&gt;checkStartDateAndEndDate(messages);&lt;br /&gt;//more validations go here&lt;br /&gt;if (!messages.empty())&lt;br /&gt;  throw new ValidationException(messages);&lt;br /&gt;}&lt;br /&gt;&lt;br /&gt;private void checkStartDateAndEndDate(Messages messages) {&lt;br /&gt;if (Util.empty(startDate) || Util.empty(endDate)) {&lt;br /&gt;  if (Util.empty(startDate))&lt;br /&gt;    messages.addError(Messages.ENTER_START_DATE);&lt;br /&gt;  if (Util.empty(endDate))&lt;br /&gt;    messages.addError(Messages.ENTER_END_DATE);&lt;br /&gt;} else if (Util.before(endDate, startDate)) {&lt;br /&gt;  messages.addError(Messages.START_DATE_MUST_PRECEDE_END_DATE,&lt;br /&gt;  startDate, endDate)&lt;br /&gt;}&lt;br /&gt;}&lt;/span&gt;&lt;/pre&gt;I think it's important to avoid performing domain object validation in setting methods, and instead to collect these validations in a single method. The reason, as stated in my earlier posts, is so this method can be called to validate dependencies from different objects, not just when this particular object is being instantiated or modified. However, what of getting methods or methods that calculate or process (the difference between such methods and simple getting methods is not obvious to me. I consider it to be the difference between methods called during basic data entry vs. methods that are called afterwards)? It's not possible to avoid validating while processing, at least I don't think so in most cases. I  am not sure, it may be possible in theory, but in practice you really can't validate all the possible results of calculations before actually performing those calculations. Therefore there will always be method calls on objects which can generate meaninful exceptions (i.e. not bugs) even though the validation methods used to save objects entered into the system have all passed. I suggest using a different type of exception when throwing these kinds of errors, maybe something like ProcessingException instead of ValidationException. In a language with compile-time exception checking, that has the added benefit of helping to make sure that you are not calling methods that throw ProcessingException inside of your validation methods.&lt;div class="blogger-post-footer"&gt;&lt;img width='1' height='1' src='https://blogger.googleusercontent.com/tracker/10784478-115962512117656047?l=vladimirlevin.blogspot.com' alt='' /&gt;&lt;/div&gt;</content><link rel='replies' type='application/atom+xml' href='http://vladimirlevin.blogspot.com/feeds/115962512117656047/comments/default' title='Post Comments'/><link rel='replies' type='text/html' href='http://www.blogger.com/comment.g?blogID=10784478&amp;postID=115962512117656047' title='1 Comments'/><link rel='edit' type='application/atom+xml' href='http://www.blogger.com/feeds/10784478/posts/default/115962512117656047'/><link rel='self' type='application/atom+xml' href='http://www.blogger.com/feeds/10784478/posts/default/115962512117656047'/><link rel='alternate' type='text/html' href='http://vladimirlevin.blogspot.com/2006/09/validation-iv.html' title='Validation IV'/><author><name>Vladimir Levin</name><uri>http://www.blogger.com/profile/09680919094932667147</uri><email>noreply@blogger.com</email><gd:image rel='http://schemas.google.com/g/2005#thumbnail' width='21' height='32' src='http://2.bp.blogspot.com/_zD5Hp0u_Wi0/SqSQJLR_0_I/AAAAAAAAADE/l8j4ET6y63E/S220/vlad_korean.jpg'/></author><thr:total>1</thr:total></entry><entry><id>tag:blogger.com,1999:blog-10784478.post-115911760109110462</id><published>2006-09-24T10:05:00.000-07:00</published><updated>2006-10-21T07:41:51.890-07:00</updated><title type='text'>Validation III</title><content type='html'>This post is a continuation of my original article about &lt;a href="http://vladimirlevin.blogspot.com/2006/09/validation.html"&gt;validation&lt;/a&gt;. In that post I brought up as an example the case of multiple oil wells connecting to a single battery, where a battery - for the sake of simplicity in this example - is just a tank that stores the production from all of the wells. Again as a simplifying conceit, I brought up the idea that the battery and wells connected to it should always be of the same &lt;span style="font-style: italic;"&gt;color&lt;/span&gt;. Having set up a red battery and hooked up a bunch of red wells to it, I then brought up the problem of validation deadlock: What do you do if you realize that you meant to make the battery blue, and the wells should be blue as well? Assuming you always validate all of the wells at a battery when you make changes to the battery's attributes, and also that you validate each well when you change its attributes, you wouln't be able to save your changes from red to blue. Changing the battery would produce an error message stating that there are red wells connected to it; changing a well would generate a validation error stating that the well is connected to a red battery. We're stuck!&lt;br /&gt;&lt;br /&gt;One can take several approaches to tackle this problem, and the particular approach one decides on really depends on the application itself. One idea might be to simply not permit updating. In the case of our ongoing example, users would have to delete the wells and the battery and start over again, entering the data in correctly. This simple approach may actually work for some cases where the information is quick and easy to enter, but it's not a very good idea most of the time. Having users re-enter data for all wells and for the battery too would likely be too time-consuming and frustrating, especially just to correct a simple data entry mistake.&lt;br /&gt;&lt;br /&gt;Another approach, my favourite when I can get away with it, is to allow users to make changes on the user interface one at a time, then to save those changes all at once. Behind the scenes, the application deletes and re-create everything from scratch. This kind of approach generally requires that all of the data being worked on can be managed on a single screen. In the case of the battery-wells example and similar scenarios, one can imagine first displaying the battery data at the top of the screen, then each well in a list below. Clicking on a well would make its attributes editable. A disadvantage of this approach is if the user is happily typing away making changes, and the application suddenly crashes (or in the case of a Web app, the user accidentally closes the window) all those changes are gone and must be re-entered. Such difficulties can be overcome by periodically saving the data behind the scenes - to the session for example in the case of a Web app. Finally two last points: Deleting and re-creating also doesn't work well if there are other dependencies in the system on the existing objects. Finally, performance would likely be a problem if there were a lot of data to delete and then recreate. So, in the case of a pure composition* relationship, this simple approach could work, but not in the case of aggregation**. It would probably not be a suitable solution to our well-battery problem.&lt;br /&gt;&lt;br /&gt;A variation on this approach is to defer validation until the unit of work (or transaction) is ready to be committed. One can wait until that time to call the validation method on all objects inside the unit of work. This approach also solves the validation deadlock problem if all of the changes can be made in one unit of work. The description I gave above of one single screen that allows the user to edit both the battery and all of its wells in one go is an example of a case where I think this approach would work. If however the battery is on one form and each well also has its own form, this idea won't help.&lt;br /&gt;&lt;br /&gt;* Composition is the idea that an object is made up of constituent objects which have no life of their own. That means that when you delete the main object all of its parts can be safely deleted as well. There are never any external dependecies on these parts. Pure composition is fairly rare in the software world, even in cases where it seems to be the right answer at first glance. For example, going back to our ongoing example, it might seem reasonable to delete all the wells associated with a battery along with the battery itself. However, those wells might be connected to different batteries later or earlier in time. Here's an example of composition from the application I am currently working on. There are meters in this application which measure volumes of oil and gas. At a sales meter, you may enter in the amount of oil sold in a month. You can also enter in priorities for that meter to define how the sales are allocated. You may want to first allocate sales to a particular producer, then to the rest. Since these priorities are defined for one meter and one meter alone, they can be deleted along with the meter itself.&lt;br /&gt;&lt;br /&gt;** Aggregation is the notion that an object contains other objects, but that these other objects do have a life of their own. A very typical example is a university course catalog. You have courses and students enrolled in those courses. A student can be enrolled in many courses at once, and if you delete a course from the system, you definitely don't want the system to delete all of the students who may be enrolled in it at the same time.&lt;br /&gt;&lt;br /&gt;Let's say that the preceding strategies are not the right answer for our battery-well example. What can we do then? One solution that I personally like is to put the power to validate in the hands of the user. You can let the user toggle validation. If we have a convenient single validation method for each relevant domain object as discussed earlier, that's fairly easy to do. If the validation flag is turned off, the validation method simply isn't called, and the information entered is saved even if it is invalid. One can also alter the behaviour of this method to generate warnings instead of errors. That way the user still sees all messages that the validation produces, but it doesn't prevent saving changes. In order to work with the application beyond just data entry, presumably the user would have to toggle the validation back on. You have to be careful that subsequent validation don't rely on previous ones. For example, if the first validation checked that a particular attribute is not null and a subsequent uses that attribute, you will have to put up guards to validate only if the attribute is set.&lt;br /&gt;&lt;br /&gt;One can also remove the notion of a user manually disabling validation by having the validation method generate warnings when it is called during data entry, then have it automatically produce errors when it is triggered prior to processing that actually uses the information that was entered into the system.&lt;br /&gt;&lt;br /&gt;That's about it. I will finish up by discussing a few odds and ends. I've encountered an application that was split in two. There was a 'staging area' application. In this application users were able to enter in whatever data they wanted. The application would generate warnings for inappropriate data. Once the data was 'clean', the data was then transferred into the 'production area'. Here no errors were allowed. I don't know how well this worked out as I wasn't actually working on this application, but it's not a solution I'd recommend. First it means more programming. Second, it means the whole process of using the system becomes much more involved. Finally, it doesn't solve the validation deadlock problem. What do you do if you realize you've promoted data to the production system with mutual dependencies that both need to be changed? A very simple, but in my opinion inelegant, solution to the validation deadlock problem is going through the backdoor. That is, issuing a SQL statement to update all of the appropriate records at one time. Since this bypasses the application layer entirely, there is no need to worry about validation. Even if there are database constraints in place, these can usually be deferred until the transaction is ready to be committed. While I believe this technique has its place, it's not a good idea in general. It requires outside intervention in most cases, since few users know enough about databases and SQL to do it themselves, and it is quite error prone since as I mentioned earlier, it bypasses the application.&lt;div class="blogger-post-footer"&gt;&lt;img width='1' height='1' src='https://blogger.googleusercontent.com/tracker/10784478-115911760109110462?l=vladimirlevin.blogspot.com' alt='' /&gt;&lt;/div&gt;</content><link rel='replies' type='application/atom+xml' href='http://vladimirlevin.blogspot.com/feeds/115911760109110462/comments/default' title='Post Comments'/><link rel='replies' type='text/html' href='http://www.blogger.com/comment.g?blogID=10784478&amp;postID=115911760109110462' title='0 Comments'/><link rel='edit' type='application/atom+xml' href='http://www.blogger.com/feeds/10784478/posts/default/115911760109110462'/><link rel='self' type='application/atom+xml' href='http://www.blogger.com/feeds/10784478/posts/default/115911760109110462'/><link rel='alternate' type='text/html' href='http://vladimirlevin.blogspot.com/2006/09/validation-iii.html' title='Validation III'/><author><name>Vladimir Levin</name><uri>http://www.blogger.com/profile/09680919094932667147</uri><email>noreply@blogger.com</email><gd:image rel='http://schemas.google.com/g/2005#thumbnail' width='21' height='32' src='http://2.bp.blogspot.com/_zD5Hp0u_Wi0/SqSQJLR_0_I/AAAAAAAAADE/l8j4ET6y63E/S220/vlad_korean.jpg'/></author><thr:total>0</thr:total></entry><entry><id>tag:blogger.com,1999:blog-10784478.post-115854884619605594</id><published>2006-09-17T19:41:00.000-07:00</published><updated>2006-10-21T07:41:51.836-07:00</updated><title type='text'>Validation II</title><content type='html'>This is a continuation of my &lt;a href="http://vladimirlevin.blogspot.com/2006/09/validation.html"&gt;previous posting about validation&lt;/a&gt;. When validating attributes on an object, the setting method on the attribute would seem to be the most obvious place for validation logic. However, this presents problems when the object must be validated externally. The first example I described in my earlier post concerned the need to validate all the wells associated with a battery when saving the battery - because changing an attribute on a battery could be invalid given the state of wells already attached to that battery. Since the wells themselves already exist, one wouldn't be calling any of the setting methods! A solution I generally adopt to this kind of problem is to write a 'valid' or 'isValid' method for each domain object - in fact I think it's a good idea (in languages like Java and C#) to define an interface (Validatable?) with this method and to implement it for all domain objects. That way, the valid method can be called after all attributes on an object have been set. This method can then also be called by the battery for each well. In my next posting I will discuss the validation deadlock problem.&lt;div class="blogger-post-footer"&gt;&lt;img width='1' height='1' src='https://blogger.googleusercontent.com/tracker/10784478-115854884619605594?l=vladimirlevin.blogspot.com' alt='' /&gt;&lt;/div&gt;</content><link rel='replies' type='application/atom+xml' href='http://vladimirlevin.blogspot.com/feeds/115854884619605594/comments/default' title='Post Comments'/><link rel='replies' type='text/html' href='http://www.blogger.com/comment.g?blogID=10784478&amp;postID=115854884619605594' title='3 Comments'/><link rel='edit' type='application/atom+xml' href='http://www.blogger.com/feeds/10784478/posts/default/115854884619605594'/><link rel='self' type='application/atom+xml' href='http://www.blogger.com/feeds/10784478/posts/default/115854884619605594'/><link rel='alternate' type='text/html' href='http://vladimirlevin.blogspot.com/2006/09/validation-ii.html' title='Validation II'/><author><name>Vladimir Levin</name><uri>http://www.blogger.com/profile/09680919094932667147</uri><email>noreply@blogger.com</email><gd:image rel='http://schemas.google.com/g/2005#thumbnail' width='21' height='32' src='http://2.bp.blogspot.com/_zD5Hp0u_Wi0/SqSQJLR_0_I/AAAAAAAAADE/l8j4ET6y63E/S220/vlad_korean.jpg'/></author><thr:total>3</thr:total></entry><entry><id>tag:blogger.com,1999:blog-10784478.post-115845625936935381</id><published>2006-09-16T18:17:00.000-07:00</published><updated>2006-10-21T07:41:51.778-07:00</updated><title type='text'>Validation</title><content type='html'>Validating state may not the most exciting aspect of software development, but it's important for just about all applications. It's also a challenging area, because validation requirements vary from one application to another. The topic of validation is something I've been thinking about for years now, and in this post I will try to outline some of my thoughts about it.&lt;br /&gt;&lt;br /&gt;I'll start with a common validation problem. It's one that occurs in many applications I've worked on. I'll call it the Validation Deadlock Problem. Snazzy, huh? Most application allow users to  work with data via separate data entry screens. As an example, the application I am currently working on has data entry screens for 'wells' and for 'batteries'. When you create a well, you have to connect it to a battery. Only certain kinds of wells can be allowed to connect to certain kinds of batteries. Let's say for the sake of simplicity that wells and batteries have to be the same 'color'. The first step is to create a battery. Then you can create a well and hook it up to that battery. Once you've established the connection though, you can go back and change the  well or the battery. Generally one wishes to validate all objects in an application before they are actually saved to the database. However, that's not always easy. Let's say you've realized that you set up your well/battery combination incorrectly. You had a 'red' well connected to a 'red' battery, but actually both should be 'blue'.&lt;br /&gt;&lt;br /&gt;This presents two problems for validation. The first problem is that when you change the battery, you can't just validate its own state alone. You also have to validate the wells connected to it. There is a perfomance cost to validate all the wells connected to a battery every time you make a change on the battery screen, and it may annoy users that editting a single field is slower than they expect. That's the first problem. The second problem is the dreaded validation deadlock: Assuming you bite the bullet and validate all the wells every time you save a battery, you try to change the battery to blue but you get a validation message saying that you have a red well attached to that battery. The difficulty is that you also can't change the well to blue because it's still connected to a red battery. The particularly annoying aspect of this problem is that in order for the user to be able to change both the battery and well(s) to blue, the well object(s) or the battery object must be allowed to go into an invalid state and saved that way to the database, in other words, across transactional boundaries. Generally the goal is to make sure all objects are always in a consistent state before they are persisted, but here that seems impossible. In my next posting I will explore some solutions to the two problems I've described.&lt;div class="blogger-post-footer"&gt;&lt;img width='1' height='1' src='https://blogger.googleusercontent.com/tracker/10784478-115845625936935381?l=vladimirlevin.blogspot.com' alt='' /&gt;&lt;/div&gt;</content><link rel='replies' type='application/atom+xml' href='http://vladimirlevin.blogspot.com/feeds/115845625936935381/comments/default' title='Post Comments'/><link rel='replies' type='text/html' href='http://www.blogger.com/comment.g?blogID=10784478&amp;postID=115845625936935381' title='0 Comments'/><link rel='edit' type='application/atom+xml' href='http://www.blogger.com/feeds/10784478/posts/default/115845625936935381'/><link rel='self' type='application/atom+xml' href='http://www.blogger.com/feeds/10784478/posts/default/115845625936935381'/><link rel='alternate' type='text/html' href='http://vladimirlevin.blogspot.com/2006/09/validation.html' title='Validation'/><author><name>Vladimir Levin</name><uri>http://www.blogger.com/profile/09680919094932667147</uri><email>noreply@blogger.com</email><gd:image rel='http://schemas.google.com/g/2005#thumbnail' width='21' height='32' src='http://2.bp.blogspot.com/_zD5Hp0u_Wi0/SqSQJLR_0_I/AAAAAAAAADE/l8j4ET6y63E/S220/vlad_korean.jpg'/></author><thr:total>0</thr:total></entry><entry><id>tag:blogger.com,1999:blog-10784478.post-115432625454514303</id><published>2006-07-30T22:32:00.000-07:00</published><updated>2006-10-21T07:41:51.724-07:00</updated><title type='text'>Ravi's Post About Boring Enterprise Software</title><content type='html'>I really enjoy reading Ravi Mohan's blog. Recently I read an entertaining post about enterprise software development, and how truly boring it is, in response to a blog posted originally by Martin Fowler. Here it is, "&lt;a href="http://ravimohan.blogspot.com/2006/07/but-martin-enterprise-software-is.html"&gt;But Martin, Enterprise Software &lt;span style="font-style: italic;"&gt;Is&lt;/span&gt; Boring!&lt;/a&gt;" Hehe. :)&lt;br /&gt;&lt;br /&gt;In reading Ravi's post, I thought about a few things, like what makes software development fun and interesting. Ultimately, I came to the conclusion that software has a number of dimensions to it. The first cool thing about software is that you get to build something incredibly interactive. Software has a magical quality to it. It's almost mystical. Most things in life, you can kind of see  how they work; they're physical. But on a computer, you just click on some keys for a while and all sorts of things may appear on the screen. You can make a video game, a business application, a compiler. It's amazing! The first computer I remember using was the Commodore 64. I learned the "poke" command and would poke in random numbers. Sometimes the screen would change color; sometimes nothing would happen; sometimes the system would just go wonky. The amount of technology the goes into making that sort of thing possible is truly vertiginous - from the design itself to physical manufacturing of all of the circuits and I/O to the logic of the operating system and device drivers, and finally to the development environment and compiler or interpreter. A few hundred dollars worth of hardware and software that anyone can pick up at a local electronic outlet represents the penultimate technological achievement of our age. They're so ubiquitous that we tend to forget how extraordinary computers really are. When we program, we have a kind of deep connection to this incredible phenomenon.&lt;br /&gt;&lt;br /&gt;I think there are different personalities in the software dev world. Some dimensions of software development are only barely visible to the end user. In XP, when making a new piece of software they are often labeled "motherhood stories." Performance is one of them, perhaps the most common. In business software, often called enterprise software, it is often easier to spend 10, 20, or 50k on improved hardware rather than optimize memory or cpu. From a user's point of view, the software either performs adequately or it doesn't. How one gets there doesn't matter much to the user. Some developers really enjoy the challenge of finding creative solutions to such problems, and reasonably often, simply buying hardware won't cut it. Buying hardware is the brute force solution. It's how Alexander The Great "untied" the &lt;a href="http://en.wikipedia.org/wiki/Gordian_Knot"&gt;Gordian Knot&lt;/a&gt; and went on to conquer most of the known world at the time. When it works, it works. However, in the world of operating system design, compilers, video games, and embedded systems, it is often not a reasonable solution. Here, the cleverness of systems and framework programmers comes into full force. The user requirement is very simple: Make it work with this much memory and this much cpu. The hacker then goes off and happily works away behind the scenes to make that requirement a reality. It can be an enormous amount of work that the end user never fully appreciates. Just as none of use truly appreciates the wonder of being able to flick and switch and voila, the lights are on, the TV is on, we can check our e-mail.  For the every day business programmer, most such techniques are not only un-necessary, they would probably be counterproductive; using them would lead to a less maintainable system.&lt;br /&gt;&lt;br /&gt;Another aspect that some developers are attracted to in such "hardcore" systems is novelty. I suspect that developing one's first compiler must be very interesting. I myself only ever touched the surface of compiler-writing in a University course, but I can see how the sophistication of optimization can become tantalizing. However, I think thay novelty is something that never lasts, no matter what domain one is working with. I once worked with a very smart software developer who had been in the game for 20 years. He had his own company and had written numerous compilers and interpreters. For him it was routine, and he never wanted to do it again. Ultimately, everyone must make that decision in life.  If you're only interested in novelty and the excitement of new problems, the research field is probably the best place to go. Even there, you will encounter the tedium of having to publish papers and cite references. If you're a professional software developer, one way or the other you will spend a certain amount of time learning new things, but more time building software to a customer's specification. If all you do is develop operating systems, or compilers, or quantum simulation technologies, whatever it is, soon enough you will have a standard set of tools and your main focus will be to figure out how the building blocks and tools you have fit into what your customer wants. In that respect, I think all professional software developers are in the same boat. Our main job is not to tackle a sexy new problem every day; it's to understand what are customers/users want and to provide a quality product in a timely fashion.&lt;br /&gt;&lt;br /&gt;For me, the interesting thing about software development has to do with understanding the business needs of the customer. One ability I've had to hone is the capacity to understand a customer's business on the fly. I've worked in many different areas, and within a few months of starting a project I've had to get to the point where I could probably get hired to do my customers' job, usually at an entry level I'm sure - Still, being able to understand the fundamentals of various businesses, the motivations, the potential efficiencies, that's a real skill, as valid in its own right as being able to optimize C code to operate in under an mb of ram.  Another area is modelling.&lt;br /&gt;&lt;br /&gt;Being able to model a piece of software so it's maintainable, so new features fit in nicely, while dealing with the fact that many business rules are quite arbitrary, is a difficult skill. It means walking a fine line between generaling code to avoid duplication while avoiding over-design that leads to crufty frameworks that won't accomodate tomorrow's strange and inconsistent variations. More "technical" software projects are often far neater and more orthogonal, and therefore more amenable to a general analysis. As an analogy, consider how some differential equations can be solved analytically, but most can't. There is a neatness of solving somthing completely, the the messy reality of the world is that you come up with partial solutions that suit you in practice. Anyway, I can see how a tendency to construct a complex mental model of the whole system right up front can be a good thing when developing a compiler, while it actually might be a very nasty trait when developing certain business applications.&lt;br /&gt;&lt;br /&gt;I guess my point is that people tend to vary quite a bit in the problem domains they're interested in or are good at solving. We tend to assume that whatever our particular area of interest or expertise is, that's the really hard thing to do. The truth is that sofware is a difficult thing to master for a reason, precisely because there are so many dimensions, and I'm sure I've only scratched the surface in this post!&lt;div class="blogger-post-footer"&gt;&lt;img width='1' height='1' src='https://blogger.googleusercontent.com/tracker/10784478-115432625454514303?l=vladimirlevin.blogspot.com' alt='' /&gt;&lt;/div&gt;</content><link rel='replies' type='application/atom+xml' href='http://vladimirlevin.blogspot.com/feeds/115432625454514303/comments/default' title='Post Comments'/><link rel='replies' type='text/html' href='http://www.blogger.com/comment.g?blogID=10784478&amp;postID=115432625454514303' title='2 Comments'/><link rel='edit' type='application/atom+xml' href='http://www.blogger.com/feeds/10784478/posts/default/115432625454514303'/><link rel='self' type='application/atom+xml' href='http://www.blogger.com/feeds/10784478/posts/default/115432625454514303'/><link rel='alternate' type='text/html' href='http://vladimirlevin.blogspot.com/2006/07/ravis-post-about-boring-enterprise.html' title='Ravi&apos;s Post About Boring Enterprise Software'/><author><name>Vladimir Levin</name><uri>http://www.blogger.com/profile/09680919094932667147</uri><email>noreply@blogger.com</email><gd:image rel='http://schemas.google.com/g/2005#thumbnail' width='21' height='32' src='http://2.bp.blogspot.com/_zD5Hp0u_Wi0/SqSQJLR_0_I/AAAAAAAAADE/l8j4ET6y63E/S220/vlad_korean.jpg'/></author><thr:total>2</thr:total></entry><entry><id>tag:blogger.com,1999:blog-10784478.post-115369858609831031</id><published>2006-07-23T16:47:00.000-07:00</published><updated>2006-10-21T07:41:51.664-07:00</updated><title type='text'>Software Testing</title><content type='html'>&lt;pre&gt;&lt;tt&gt;These are some notes from an evening course I've taught at the&lt;br /&gt;University Of Calgary in Continuing Education for a few years.&lt;br /&gt;Eventually I hope to organize them better and merge them into&lt;br /&gt;something more whole and coherent, but for now here they are so&lt;br /&gt;I won't forget where I put them!&lt;br /&gt;&lt;br /&gt;&lt;br /&gt;Unit Testing and Refactoring&lt;br /&gt;============================&lt;br /&gt;&lt;br /&gt;The topic of this class is TDD, or Test-Driven Development. TDD is&lt;br /&gt;about developing high quality code, keeping the design simple, and&lt;br /&gt;having a regression framework in place for code maintenance. However,&lt;br /&gt;TDD is not sufficient to insure the quality of commercial or&lt;br /&gt;enterprise applications. In general terms, I break down testing&lt;br /&gt;into three general categories:&lt;br /&gt;&lt;br /&gt;I) Developer Tests (TDD)&lt;br /&gt;II) QA Tests&lt;br /&gt;III) User Acceptance Tests&lt;br /&gt;&lt;br /&gt;Each category is somewhat different from the others. The primary&lt;br /&gt;goal of developer testing is a strong design, high code quality, and&lt;br /&gt;low defect rates.&lt;br /&gt;&lt;br /&gt;I) Developer Tests (TDD)&lt;br /&gt;&lt;br /&gt;In TDD, a developer always writes a test first, before writing any&lt;br /&gt;code. The steps in TDD are always the same:&lt;br /&gt;&lt;br /&gt;1) Write a test&lt;br /&gt;2) Make sure the test fails as expected. If there are new classes or&lt;br /&gt; methods involved, then the test won't even compile in a language&lt;br /&gt; like Java or C#.Net. If the function already exists, but the&lt;br /&gt; code inside has been modified, then make sure the test&lt;br /&gt; initially fails the way you expect it to fail. Let's say you&lt;br /&gt; have a function which calculates change for a purchase and you&lt;br /&gt; are writing a test to cause it to break change down differently&lt;br /&gt; depending on the quanities of available denominations; so whereas&lt;br /&gt; it currently returns one quarter, it is supposed to return two&lt;br /&gt; dimes and a nickle. Make sure the test fails initially by returning&lt;br /&gt; a quarter (as opposed to simply crashing or actually returning the&lt;br /&gt; right change before you've modified the code.&lt;br /&gt;3) Write the new code and make sure the tests now all pass.&lt;br /&gt;4) Examine the design and refactor any duplication (I'll discuss&lt;br /&gt; refactoring in more detail in another class).&lt;br /&gt;&lt;br /&gt;That's it, now rinse and repeat!&lt;br /&gt;&lt;br /&gt;I'd like to make it clear that the goals of TDD are somewhat&lt;br /&gt;different from the goals of other kinds of testing. TDD is&lt;br /&gt;a development activity. The goal of TDD is first and foremost&lt;br /&gt;to drive the design of the code itself. Using TDD ought to&lt;br /&gt;generate code in which independent concerns are expressed in&lt;br /&gt;separate pieces of code. Such separation makes it easier to&lt;br /&gt;test the code. If the code is hard to test, that implies the&lt;br /&gt;design of the code is not optimal. If the code is easy to&lt;br /&gt;test, then the design of the code is better. Better code means&lt;br /&gt;it's easier to add new features and it also means the QA people&lt;br /&gt;will find fewer defects, and especially should find almost no&lt;br /&gt;defects related to basic functionality.&lt;br /&gt;&lt;br /&gt;You can look at an application as a bunch of nested boxes. The&lt;br /&gt;innermost box is the code framework you're using to develop on&lt;br /&gt;top of. It's there before you've written a single line of your&lt;br /&gt;own code. Then you develop code around that kernel. The code&lt;br /&gt;tends to become organized in ever wider layers, although some&lt;br /&gt;"inner" layers may depend on outer layers, so the layering&lt;br /&gt;is rarely "perfect." Still, good code generally has this sort of&lt;br /&gt;hierarchical structure:&lt;br /&gt; _____________&lt;br /&gt;[    __A__    ]&lt;br /&gt;[   [  B  ]   ]&lt;br /&gt;[   [ [C] ]   ]&lt;br /&gt;[   [_____]   ]&lt;br /&gt;[_____________] etc...&lt;br /&gt;&lt;br /&gt;If you're writing tests for code in B the general approach is&lt;br /&gt;as follows: If necessary, you can "mock" out functionality in C&lt;br /&gt;by subsituting a mock/stub/fake instead of the real code in C.&lt;br /&gt;This kind of thing is done when the real code in C accesses&lt;br /&gt;external resources which are irrelevant to testing the logic in B.&lt;br /&gt;Having extensively tested B by itself, you would then write&lt;br /&gt;a comparatively small number of tests against the application&lt;br /&gt;as a whole making sure that the code in B is actually used by&lt;br /&gt;the application. Such "sanity" tests will make sure the code in B&lt;br /&gt;really has been included in the app and works for a few basic&lt;br /&gt;cases. You can think of such "functional" tests as poking lines&lt;br /&gt;through the outer layer of the application all the way through.&lt;br /&gt;Note, do not confuse a functional test in TDD with a FIT test,&lt;br /&gt;which is a functional integration test. The extensive testing has&lt;br /&gt;already been done, so even though these functional tests do not&lt;br /&gt;test every path through B, they make sure it's properly fitted&lt;br /&gt;into the application as a whole.&lt;br /&gt;&lt;br /&gt;A functional test through B looks something like this:&lt;br /&gt;     ____\__________&lt;br /&gt;[    _\_A___    ]&lt;br /&gt;[   [  \B   ]   ]&lt;br /&gt;[   [  [\C] ]   ]&lt;br /&gt;[   [_______]   ]&lt;br /&gt;[_______________] etc...&lt;br /&gt;&lt;br /&gt;&lt;br /&gt;You can see it's hard to write enough tests like this to properly&lt;br /&gt;cover B. That's what the unit tests are for.&lt;br /&gt;&lt;br /&gt;Here is an eample unit test in Java-like syntax (modified from real&lt;br /&gt;Java to make the example more readable):&lt;br /&gt;&lt;br /&gt;public void&lt;br /&gt;      testCalculateChange_WithChangeLevelling() {&lt;br /&gt;  //setup&lt;br /&gt;  VendingMachine vm = new VendingMachine();&lt;br /&gt;  vm.setNumberOfQuarters(10);&lt;br /&gt;  vm.setNumberOfDimes(100);&lt;br /&gt;  vm.setNumberOfNickles(100);&lt;br /&gt;&lt;br /&gt;  //execute&lt;br /&gt;  int[] change = vm.makeChange(25);&lt;br /&gt;&lt;br /&gt;  //assert&lt;br /&gt;  assertEquals("use nickles and dimes", [10, 10, 5], change);&lt;br /&gt;}&lt;br /&gt;&lt;br /&gt;Note: Before implementing the "levelling" algorithm, the test should&lt;br /&gt;return [25] instead of the expected [10, 10, 5]. Note that this test&lt;br /&gt;just tests the makeChange function. It does not worry about how the&lt;br /&gt;amount of change itself if calculated. A functional test would&lt;br /&gt;be more complicated because more setup would be required, but&lt;br /&gt;there are generally fewer of these per feature:&lt;br /&gt;&lt;br /&gt;public void&lt;br /&gt;      testFunctionalTest_Purchase_WithChangeLevelling() {&lt;br /&gt;  //setup&lt;br /&gt;  VendingMachine vm = new VendingMachine();&lt;br /&gt;  vm.setNumberOfQuarters(10);&lt;br /&gt;  vm.setNumberOfDimes(100);&lt;br /&gt;  vm.setNumberOfNickles(100);&lt;br /&gt;  vm.addItem("Mars Bar", "$0.75", 15); //15 mars bars; 75 cents&lt;br /&gt;&lt;br /&gt;  //execute&lt;br /&gt;  int[] change = vm.purchase("Mars Bar", "$1.00");&lt;br /&gt;&lt;br /&gt;  //assert&lt;br /&gt;  assertEquals("use nickles and dimes", [10, 10, 5], change);&lt;br /&gt;}&lt;br /&gt;&lt;br /&gt;&lt;br /&gt;II) QA testing is done with a build of the application provided by&lt;br /&gt;the developers. Therefore QA testing is done after a certain amount of&lt;br /&gt;code has been developed. QA testing is usually done by QA&lt;br /&gt;professionals often with support from users  or business people to&lt;br /&gt;make sure the developed software really does work and meets the user&lt;br /&gt;requirements.  Some QA testing can be automated with scripts. On&lt;br /&gt;our project, we use a tool called Watir (&lt;a href="http://wtr.rubyforge.org/%29" target="_blank"&gt;http://wtr.rubyforge.org/)&lt;/a&gt;&lt;br /&gt;to script interactions with the Web application as if a real user&lt;br /&gt;were clicking on buttons and entering data.&lt;br /&gt;&lt;br /&gt;III) User acceptance tests are generally written before the&lt;br /&gt;application code has been developed. The format of the tests is&lt;br /&gt;a table with the inputs entered in by the user and expected outputs.&lt;br /&gt;Later, such tests are linked in with the application and executed&lt;br /&gt;to determine whether they've passed. FIT (&lt;a href="http://fit.c2.com/%29" target="_blank"&gt;http://fit.c2.com/)&lt;/a&gt;&lt;br /&gt;and Fitnesse (&lt;a href="http://fitnesse.org/%29" target="_blank"&gt;http://fitnesse.org/)&lt;/a&gt; are tools commonly used in&lt;br /&gt;the XP community for such "functional integration" testing.&lt;br /&gt;&lt;br /&gt;&lt;br /&gt;&lt;br /&gt;&lt;br /&gt;&lt;/tt&gt;&lt;/pre&gt;           &lt;!-- toctype = X-unknown --&gt;&lt;!-- toctype = text --&gt;&lt;!-- text --&gt;&lt;!-- END TOC --&gt; &lt;input name=".crumb" value="p.N3tZG/WXw" type="hidden"&gt;&lt;input name="MsgId" value="7351_0_959_506_3076_0_110469_6749_3739579430_oSObkYn4Ur5HQV71mWzmsQqQcG8oeZcLRMf.FGdYDd_lz8Wk_m.wNzKqwHiFLEyYJddhi0_grj.2g02Qze9D5my45QaKgM99HwlKzA6AwMw68CBprq1UdyK6ec0mY0z6PKR_W2Cuem0z3_rbTXUWkcM64bAY" type="hidden"&gt;&lt;input name="box" value="Draft" type="hidden"&gt;&lt;input name="MOV" value="" type="hidden"&gt;&lt;input name="NewFol" value="" type="hidden"&gt;&lt;input name="destBox" value="" type="hidden"&gt;&lt;input name="newfoldermessage" value="Please enter a name for your folder." type="hidden"&gt;&lt;input name="DEL" value="" type="hidden"&gt;                                                                                         &lt;span class="first"&gt; &lt;button type="button" name="delete" id="deletebottom" value="Delete" onclick="Delete_Click(this);"&gt;Delete&lt;/button&gt;        &lt;button type="button" value="Reply" id="replybottom" class="hasdefaultstate"&gt;Reply&lt;/button&gt;    &lt;button type="button" value="Forward" id="forwardbottom" class="hasdefaultstate"&gt;Forward&lt;/button&gt;&lt;/span&gt;&lt;div class="blogger-post-footer"&gt;&lt;img width='1' height='1' src='https://blogger.googleusercontent.com/tracker/10784478-115369858609831031?l=vladimirlevin.blogspot.com' alt='' /&gt;&lt;/div&gt;</content><link rel='replies' type='application/atom+xml' href='http://vladimirlevin.blogspot.com/feeds/115369858609831031/comments/default' title='Post Comments'/><link rel='replies' type='text/html' href='http://www.blogger.com/comment.g?blogID=10784478&amp;postID=115369858609831031' title='0 Comments'/><link rel='edit' type='application/atom+xml' href='http://www.blogger.com/feeds/10784478/posts/default/115369858609831031'/><link rel='self' type='application/atom+xml' href='http://www.blogger.com/feeds/10784478/posts/default/115369858609831031'/><link rel='alternate' type='text/html' href='http://vladimirlevin.blogspot.com/2006/07/software-testing.html' title='Software Testing'/><author><name>Vladimir Levin</name><uri>http://www.blogger.com/profile/09680919094932667147</uri><email>noreply@blogger.com</email><gd:image rel='http://schemas.google.com/g/2005#thumbnail' width='21' height='32' src='http://2.bp.blogspot.com/_zD5Hp0u_Wi0/SqSQJLR_0_I/AAAAAAAAADE/l8j4ET6y63E/S220/vlad_korean.jpg'/></author><thr:total>0</thr:total></entry><entry><id>tag:blogger.com,1999:blog-10784478.post-115051507780658765</id><published>2006-06-16T20:02:00.000-07:00</published><updated>2006-10-21T07:41:51.544-07:00</updated><title type='text'>Agile In Action</title><content type='html'>I don't know to what extent the notions of up-front requirements analysis and design are still being actively used these days, but I've heard a lot of debate on the subject over the past few years. I'm currently working on an agile project and today I had a good experience in which three of us, a customer and two developers, worked together to flesh out a requirement in a way that simply would not be possible in a more traditional environment heavy on up-front requirement preparation. Since this is an example from the real world, I'll be using project-specific terminology, but I hope to make the general sense of what's going on clear to anyone reading this blog. If you're reading this and have something to say that may clarify matters, I encourage you to &lt;a href="mailto://vladimir_levin@yahoo.ca"&gt;e-mail me&lt;/a&gt; and I'll update this posting.&lt;br /&gt;&lt;br /&gt;In our application (oil and gas production accounting), we have the notion of a gas-equivalent factor (ge factor). It is a number that you multiply by a volume of light oil, also called condensate, to get an "equivalent" volume of gas. It's a bit like comparing, say, two grads from different schools. One grad has a GPA of 3.2 and the other one has a 78% average. To compare them, you may want to convert the gpa of 3.2 to a percentage, or vice versa. Anyway, the point is that this number is displayed on several screen of the application. Now, there are several different ways that this number is obtained, and as part of a story I was working on, I had to include the source of the ge factor along with the number itself. The story (similar to a use case) specified that one of two icons should be displayed along with the factor: "A" for analysis, and "E" for entered. In one case, an analysis (a breakdown of the molecular constituents of the condensate) is used to calculate a ge factor; in the other case, the user simply enters in the factor manually. As I began to get into code, I realized that there was a third case that the story didn't talk about. I turned to the customer who had put together the story, who sits just across from me, and asked him about it: Al, what happens when the ge factor is not necessarily derived from an analysis, but it's averaged from ge factors at several other measurements? After a bit of discussion, the user and I agreed to include a third icon as part of the story, "C" for calculated.&lt;br /&gt;&lt;br /&gt;I implemented the requirement simply by putting a text label "A", "C", or "E" next to the ge factors on the appropriate screens. Then I went to talk to our resident gui (graphical user interface) expert about the story: Hey Chris, I've put these text labels next to the ge factor on our balancing screens. Could you cook up some icons that look a bit nicer? Chris came over and asked Al: What if instead of an extra icon next to the factor, we turned the factor itself into a link. If the number came from an analysis, the link would actually take the user to the analysis that was used. If the number was entered, the link would lead to the screen where that number was entered. The user really liked this idea. I objected: In the case that the number was calculated by averaging several measurements, it would be a fair amount of work to create a new screen that showed all of those measurements in one place. The user however told us that it wasn't necessary to go that far. If the number was an average, simply omitting the link was fine.&lt;br /&gt;&lt;br /&gt;The buzzwordz "multidisciplinary" and "synergy" are used a lot these days, but in this case, we solved a problem by combining our skills and perspectives. Requirements are a bit like art. If you're a customer, you generally know what you want when you see it, but describing it ahead of time isn't so easy. In a non-trivial application, it's &lt;span style="font-style: italic;"&gt;hard &lt;/span&gt;to think of all the possible scenarios for a given feature. As a developer, I'm close to the code and I can &lt;span style="font-style: italic;"&gt;see &lt;/span&gt;those scenarios, so it's a lot easier for me to ask the kind of question that I asked. Finally, the user interface expert was concerned about clutter on the screen and how effective the user interface would be, whereas I just cared about the fact that the right information would show up as described in the story. We all worked together to come up with a better solution - without really extending the development time. The whole discussion probably clocked in at about 15-30 minutes, and nothing about the requirement caused an enormous amount of extra work. In the future, if someone decides to show all of the measurements that contribute to an "averaged" ge factor, we can implement that as a separate story. The important thing is that the users currently don't consider it to be especially useful or a high priority. We've built the software not to honor a general principle of orthogonality, but to meet our users' actual requirements.&lt;br /&gt;&lt;br /&gt;I was really impressed with the process we went through today and I thought it was a nice simple example the kind of power an agile approach can have.&lt;div class="blogger-post-footer"&gt;&lt;img width='1' height='1' src='https://blogger.googleusercontent.com/tracker/10784478-115051507780658765?l=vladimirlevin.blogspot.com' alt='' /&gt;&lt;/div&gt;</content><link rel='replies' type='application/atom+xml' href='http://vladimirlevin.blogspot.com/feeds/115051507780658765/comments/default' title='Post Comments'/><link rel='replies' type='text/html' href='http://www.blogger.com/comment.g?blogID=10784478&amp;postID=115051507780658765' title='0 Comments'/><link rel='edit' type='application/atom+xml' href='http://www.blogger.com/feeds/10784478/posts/default/115051507780658765'/><link rel='self' type='application/atom+xml' href='http://www.blogger.com/feeds/10784478/posts/default/115051507780658765'/><link rel='alternate' type='text/html' href='http://vladimirlevin.blogspot.com/2006/06/agile-in-action.html' title='Agile In Action'/><author><name>Vladimir Levin</name><uri>http://www.blogger.com/profile/09680919094932667147</uri><email>noreply@blogger.com</email><gd:image rel='http://schemas.google.com/g/2005#thumbnail' width='21' height='32' src='http://2.bp.blogspot.com/_zD5Hp0u_Wi0/SqSQJLR_0_I/AAAAAAAAADE/l8j4ET6y63E/S220/vlad_korean.jpg'/></author><thr:total>0</thr:total></entry><entry><id>tag:blogger.com,1999:blog-10784478.post-115007263528261843</id><published>2006-06-11T17:32:00.000-07:00</published><updated>2006-10-21T07:41:51.488-07:00</updated><title type='text'>Just-In-Time Performance Tuning</title><content type='html'>I've been thinking a bit about performance tuning business applications lately, after reading some of Ted Ogrady's recent writings on the subject (see &lt;a href="http://tedogrady.blogspot.com/2006/06/empirical-performance.html"&gt;Empirical Performance &lt;/a&gt;, &lt;a href="http://tedogrady.blogspot.com/2006/06/vlad-points-out-my-oversimplification.html"&gt;Elaboration&lt;/a&gt;, and &lt;a href="http://tedogrady.blogspot.com/2006/06/vlad-on-risk-and-performance.html"&gt;Reponse to my concerns about risk&lt;/a&gt;). Ted pointed out that some authorities in the agile realm recommend avoiding premature optimization (see &lt;a href="http://www.artima.com/intv/tunable.html"&gt;Fowler&lt;/a&gt; and &lt;a href="http://www.rolemodelsoftware.com/moreAboutUs/publications/articles/lazyopt.php"&gt;Beck&lt;/a&gt;). It's true that optimizing code early can lead to problems, and especially that one should not optimize code without profiling it first. However, I do think that letting the performance get bad enough to upset users is a bad thing, and seems out of character in agile development. For example, Kent Beck writes:&lt;br /&gt;&lt;p&gt;&lt;span style="font-size:100%;"&gt;&lt;/span&gt;&lt;/p&gt;&lt;blockquote&gt;&lt;p&gt;&lt;span style="font-size:100%;"&gt;Later, a developer pulled Kent aside and said, "You got me in trouble."&lt;/span&gt;&lt;/p&gt;  &lt;p&gt;&lt;span style="font-size:100%;"&gt;"About what?"&lt;/span&gt;&lt;/p&gt;  &lt;p&gt;&lt;span style="font-size:100%;"&gt;"You said I could tune performance after I got the design right."&lt;/span&gt;&lt;/p&gt;  &lt;p&gt;&lt;span style="font-size:100%;"&gt;"Yes, I did. What happened?"&lt;/span&gt;&lt;/p&gt;  &lt;p&gt;&lt;span style="font-size:100%;"&gt;"We spent all that time getting the design right. Then the users wanted sub-second response time. The system was taking as long as fifteen seconds to respond to a query. It took me all weekend to change the design around to fix the performance problem."&lt;/span&gt;&lt;/p&gt;  &lt;p&gt;&lt;span style="font-size:100%;"&gt;"How fast is it now?"&lt;/span&gt;&lt;/p&gt;  &lt;p&gt;&lt;span style="font-size:100%;"&gt;"Well, now it comes back in a third of a second."&lt;/span&gt;&lt;/p&gt;  &lt;p&gt;&lt;span style="font-size:100%;"&gt;"So, what’s the problem?"&lt;/span&gt;&lt;/p&gt;  &lt;p&gt;&lt;span style="font-size:100%;"&gt;"I was really nervous that I wouldn’t be able to fix the performance problem."&lt;/span&gt;&lt;/p&gt;&lt;/blockquote&gt;&lt;br /&gt;Kent's suggestion is to do some envelope calculations to assess performance early in the project, but that's just a written down artifact, the kind of thing that agile practices generally discount.&lt;br /&gt;&lt;br /&gt;As I see it, the history of the performance tuning debate goes something like this: Early on, performance tuning had to be done all the time because hardware was so slow and memory was so expensive. Later on, a overall computer performance improved, there was a backlash against this kind of optimize-always behaviour. If you aren't desperately worried about memory, you don't need to use bit fields - that sort of thing. However, as a result of leaving performance issues for late in the project, I've seen a number of projects now where the performance becomes really terrible. Users get upset and the overall perception of management is not positive. The developers in this case say "Don't worry, we'll solve the performance problems later." However, these performance problems can start to affect the project. User who are testing that app spend too much time navigating from one screen to another, and even the time to run automated tests written by the development team suffers.&lt;br /&gt;&lt;br /&gt;Basically, I think there is a &lt;span style="font-style: italic;"&gt;better way:&lt;/span&gt;  One of the best idea in software development I've come across in the last while is the notion of a &lt;a href="http://fit.c2.com/"&gt;FIT test&lt;/a&gt;. A FIT test is a customer-facing test. My suggestion is to devote time to developing a relatively small number of performance-oriented FIT tests during each iteration. These tests execute an area of code where performance is important under conditions that are as realistic as possible.  Just as with normal FIT tests, performance FIT tests can be written before the actual code exists. Initially, there is no processing done and the test passes trivially. Each iteration, someone is responsible for maintaining the fit test - adding setup data and making sure it runs without errors.  If the test meets the established performance criteria, the bar is green, otherwise it's red. That's when we jump in with the profiler to get the performance back to acceptable levels. The code should remain as clean as possible, and only the minimum amount of tweaking required to make the test pass should be done. That way the users won't run across unacceptable levels of performance as the app is being developed, thus reducing risk and stress for everyone. The basic point I am trying to make is not that performance cannot be improved late in a project, but that maybe it doesn't have to be that way.&lt;div class="blogger-post-footer"&gt;&lt;img width='1' height='1' src='https://blogger.googleusercontent.com/tracker/10784478-115007263528261843?l=vladimirlevin.blogspot.com' alt='' /&gt;&lt;/div&gt;</content><link rel='replies' type='application/atom+xml' href='http://vladimirlevin.blogspot.com/feeds/115007263528261843/comments/default' title='Post Comments'/><link rel='replies' type='text/html' href='http://www.blogger.com/comment.g?blogID=10784478&amp;postID=115007263528261843' title='0 Comments'/><link rel='edit' type='application/atom+xml' href='http://www.blogger.com/feeds/10784478/posts/default/115007263528261843'/><link rel='self' type='application/atom+xml' href='http://www.blogger.com/feeds/10784478/posts/default/115007263528261843'/><link rel='alternate' type='text/html' href='http://vladimirlevin.blogspot.com/2006/06/just-in-time-performance-tuning.html' title='Just-In-Time Performance Tuning'/><author><name>Vladimir Levin</name><uri>http://www.blogger.com/profile/09680919094932667147</uri><email>noreply@blogger.com</email><gd:image rel='http://schemas.google.com/g/2005#thumbnail' width='21' height='32' src='http://2.bp.blogspot.com/_zD5Hp0u_Wi0/SqSQJLR_0_I/AAAAAAAAADE/l8j4ET6y63E/S220/vlad_korean.jpg'/></author><thr:total>0</thr:total></entry><entry><id>tag:blogger.com,1999:blog-10784478.post-114938717691295412</id><published>2006-06-03T19:04:00.000-07:00</published><updated>2006-10-21T07:41:51.426-07:00</updated><title type='text'>Further Lessons In Humility</title><content type='html'>In an &lt;a href="http://vladimirlevin.blogspot.com/2006/05/mixins-interfaces-and-multiple.html"&gt;earlier post&lt;/a&gt;, I discussed creating an abstract class Node and extending it with either TestNode (for unit tests) or Facility Node (for the actual production code) in order to move some functionality related to facility network topology out of the Facility class. I was kind of proud of my accomplishment, especially when it came to me that I had implemented a kind of "mixin" inheritance in Java. However, a friend of mine blew my bubble by pointing out that a simpler implementation existed. Namely, just move the topology code into something like a NetworkTopologyUtils class as static methods. Hence, we have something like this:&lt;br /&gt;&lt;br /&gt;public class NetworkTopologyUtils {&lt;br /&gt;public static findLoop(Node n) { /*code goes here ... */ }&lt;br /&gt;//more applicable methods below...&lt;br /&gt;}&lt;br /&gt;&lt;br /&gt;This is just as easy to test, and makes more sense, since the responsibility for finding loops no longer rests with a hard to pin down "Node" class. Now all that remains is to implement the Node  interface (e.g. sendsTo) in Facility. For unit testing, one can just as easily write a TestNode class that also implements the Node interface.&lt;br /&gt;&lt;br /&gt;What's the lesson here? For me, it's that I shouldn't fall in love with my own code. Also, I should not let my ingrained biases (against such static singleton classes for example) get in the way of putting together the right design. Finally, there's nothing wrong with keeping it simple. Simplicity is good. Even though my example wasn't a great one, I still do like mixins in Ruby though and think that Java should have implemented them (not to mention C#)! :)&lt;div class="blogger-post-footer"&gt;&lt;img width='1' height='1' src='https://blogger.googleusercontent.com/tracker/10784478-114938717691295412?l=vladimirlevin.blogspot.com' alt='' /&gt;&lt;/div&gt;</content><link rel='replies' type='application/atom+xml' href='http://vladimirlevin.blogspot.com/feeds/114938717691295412/comments/default' title='Post Comments'/><link rel='replies' type='text/html' href='http://www.blogger.com/comment.g?blogID=10784478&amp;postID=114938717691295412' title='0 Comments'/><link rel='edit' type='application/atom+xml' href='http://www.blogger.com/feeds/10784478/posts/default/114938717691295412'/><link rel='self' type='application/atom+xml' href='http://www.blogger.com/feeds/10784478/posts/default/114938717691295412'/><link rel='alternate' type='text/html' href='http://vladimirlevin.blogspot.com/2006/06/further-lessons-in-humility.html' title='Further Lessons In Humility'/><author><name>Vladimir Levin</name><uri>http://www.blogger.com/profile/09680919094932667147</uri><email>noreply@blogger.com</email><gd:image rel='http://schemas.google.com/g/2005#thumbnail' width='21' height='32' src='http://2.bp.blogspot.com/_zD5Hp0u_Wi0/SqSQJLR_0_I/AAAAAAAAADE/l8j4ET6y63E/S220/vlad_korean.jpg'/></author><thr:total>0</thr:total></entry><entry><id>tag:blogger.com,1999:blog-10784478.post-114878575170067548</id><published>2006-05-27T20:08:00.000-07:00</published><updated>2006-10-21T07:41:51.367-07:00</updated><title type='text'>SmackBook</title><content type='html'>Way COOL!&lt;br /&gt;&lt;br /&gt;&lt;a href="http://www.youtube.com/watch?v=6uvQTTPr9Rw&amp;www.reghardware.co.uk"&gt;http://www.youtube.com/watch?v=6uvQTTPr9Rw&amp;amp;www.reghardware.co.uk&lt;/a&gt;&lt;div class="blogger-post-footer"&gt;&lt;img width='1' height='1' src='https://blogger.googleusercontent.com/tracker/10784478-114878575170067548?l=vladimirlevin.blogspot.com' alt='' /&gt;&lt;/div&gt;</content><link rel='replies' type='application/atom+xml' href='http://vladimirlevin.blogspot.com/feeds/114878575170067548/comments/default' title='Post Comments'/><link rel='replies' type='text/html' href='http://www.blogger.com/comment.g?blogID=10784478&amp;postID=114878575170067548' title='0 Comments'/><link rel='edit' type='application/atom+xml' href='http://www.blogger.com/feeds/10784478/posts/default/114878575170067548'/><link rel='self' type='application/atom+xml' href='http://www.blogger.com/feeds/10784478/posts/default/114878575170067548'/><link rel='alternate' type='text/html' href='http://vladimirlevin.blogspot.com/2006/05/smackbook.html' title='SmackBook'/><author><name>Vladimir Levin</name><uri>http://www.blogger.com/profile/09680919094932667147</uri><email>noreply@blogger.com</email><gd:image rel='http://schemas.google.com/g/2005#thumbnail' width='21' height='32' src='http://2.bp.blogspot.com/_zD5Hp0u_Wi0/SqSQJLR_0_I/AAAAAAAAADE/l8j4ET6y63E/S220/vlad_korean.jpg'/></author><thr:total>0</thr:total></entry><entry><id>tag:blogger.com,1999:blog-10784478.post-114878152816585909</id><published>2006-05-27T18:43:00.000-07:00</published><updated>2006-10-21T07:41:51.309-07:00</updated><title type='text'>Mixins, Interfaces, and Multiple Inheritance</title><content type='html'>As I've been doing Ruby programming for the last little while, I've discovered the concept of Mixins. Now, my programming experience in OO languages other than Java has been limited. I only did about a year of C++ at my first job before I ended up switching to Java, so that's why I haven't really been exposed to the notion of a Mixin before. But now that I've been using it a bit, I think it is in fact a rather wonderful concept! Interestingly, I've cooked up my own erzatz mixins in Java in the past without fully realizing what I was doing, but I think proper mixins really are more elegant!&lt;br /&gt;&lt;br /&gt;A module in ruby is similar to a class with one major exception: It cannot be instantiated. You can execute methods on it statically, so for example you can have a Math module with functions like sin, consin, absolute_value, and so on. More interestingly, you can &lt;span style="font-style: italic;"&gt;mix in&lt;/span&gt; a module into a proper Ruby class, whereupon all of the module's methods become available to the class as normal member methods - and the module's methods can in fact interact with methods supplied by the class. It is similar to multiple inheritance as implemented in C++ for example, but slightly weaker. C++ has full multiple inheritance, so it can do both interfaces as implemented in Java and mixins in Ruby as special cases. To make a C++ 'interface', you create a class with all pure virtual methods. To create a 'mixin module', you create a class with some pure virtual methods and at least one fully-implemented method which calls the pure virtual methods. However, in C++, you can do even more. You can simply write any number of fully functional classes, and then create another class which extends all of them. In OO, this means that wherever you have a reference to any of those base classes, you can substitute the subclass. Thus, every method from all base classes is valid for the subclass in terms of class invariants as well as preconditions and postconditions. Both Java and Ruby designers chose not to provide that degree of generality. I am guessing they felt encouraging developers to inherit from more than one fully-functional class is asking for trouble, especially as the inheritance chain becomes more than just one level deep! Mixins are a nice compromise: You can inherit functionality from a variety of sources (better than Java), but you can't arbitraily exend any number of actual classes with all the attendant headaches.&lt;br /&gt;&lt;br /&gt;In Java, I have used delegation to do the same kind of thing that mixins provide, but without fully realizing what I was doing, until now! A while back I needed to write some code to find a loop in a network of oil facilities. Here is roughly what I did in order not to pollute the Facility class (loop finding after all is a lower-level behaviour) and to make the code easy to write test-first.&lt;br /&gt;&lt;pre&gt;&lt;tt&gt;public abstract class Node {&lt;br /&gt;public abstract List sendsTo();&lt;br /&gt;public List findLoop() {&lt;br /&gt;//recursively goes through the nodes in sendsTo.&lt;br /&gt;//If it finds itself as it's going along, it returns&lt;br /&gt;//a list of nodes that form the loop. Otherwise it&lt;br /&gt;//returns an empty list. In my implementation, if&lt;br /&gt;//there are multiple loops, only the first one&lt;br /&gt;//this method finds it returned.&lt;br /&gt;}&lt;br /&gt;}&lt;/tt&gt;&lt;/pre&gt;To get this to work with my Facility class, I implemented a class&lt;br /&gt;FacilityNode as follows:&lt;br /&gt;&lt;pre&gt;&lt;tt&gt;public class FacilityNode extends Node {&lt;br /&gt;public FacilityNode(Facility facility) {&lt;br /&gt;this.facility = facility;&lt;br /&gt;}&lt;br /&gt;public List sendsTo() {&lt;br /&gt;//return a list of all dispositions of oil from this&lt;br /&gt;//facility with non-zero volumes. Ignore dispositions&lt;br /&gt;//of gas or water, and ignore oil dispositions that have&lt;br /&gt;//0 volume.&lt;br /&gt;}&lt;br /&gt;}&lt;/tt&gt;&lt;/pre&gt; Then in the Facility class, I use this FacilityNode as follows:&lt;br /&gt;&lt;pre&gt;&lt;tt&gt;public class Facility {&lt;br /&gt;//... whole bunch of other methods&lt;br /&gt;&lt;br /&gt;public List findLoop() {&lt;br /&gt;return new FacilityNode(this).findLoop();&lt;br /&gt;}&lt;br /&gt;}&lt;/tt&gt;&lt;/pre&gt;This is admittedly far more awkward than simply mixing Node into the Facility class and implementing sendsTo, but it's the same general idea. One can see that the Node class can be expanded to include a variety of operations related to the topologies of networks and thereby provide far better overall cohesion in the application. In order to take advantage of these mixed-in methods, one need only implement a much small number of required methods, like sendsTo for example! Mixins are cool!&lt;div class="blogger-post-footer"&gt;&lt;img width='1' height='1' src='https://blogger.googleusercontent.com/tracker/10784478-114878152816585909?l=vladimirlevin.blogspot.com' alt='' /&gt;&lt;/div&gt;</content><link rel='replies' type='application/atom+xml' href='http://vladimirlevin.blogspot.com/feeds/114878152816585909/comments/default' title='Post Comments'/><link rel='replies' type='text/html' href='http://www.blogger.com/comment.g?blogID=10784478&amp;postID=114878152816585909' title='1 Comments'/><link rel='edit' type='application/atom+xml' href='http://www.blogger.com/feeds/10784478/posts/default/114878152816585909'/><link rel='self' type='application/atom+xml' href='http://www.blogger.com/feeds/10784478/posts/default/114878152816585909'/><link rel='alternate' type='text/html' href='http://vladimirlevin.blogspot.com/2006/05/mixins-interfaces-and-multiple.html' title='Mixins, Interfaces, and Multiple Inheritance'/><author><name>Vladimir Levin</name><uri>http://www.blogger.com/profile/09680919094932667147</uri><email>noreply@blogger.com</email><gd:image rel='http://schemas.google.com/g/2005#thumbnail' width='21' height='32' src='http://2.bp.blogspot.com/_zD5Hp0u_Wi0/SqSQJLR_0_I/AAAAAAAAADE/l8j4ET6y63E/S220/vlad_korean.jpg'/></author><thr:total>1</thr:total></entry><entry><id>tag:blogger.com,1999:blog-10784478.post-114843349048654506</id><published>2006-05-23T18:04:00.000-07:00</published><updated>2006-10-21T07:41:51.199-07:00</updated><title type='text'>Mindless Ranting</title><content type='html'>When I talk about calling a function on an object, I use the word "method." I have no idea where it all started - probably those &lt;a href="http://www.amazon.com/gp/product/0201633612/sr=8-1/qid=1148432920/ref=pd_bbs_1/002-9596092-0405641?%5Fencoding=UTF8"&gt;4 gangtas&lt;/a&gt; started it. Those ghetto kids, always coming up with the crazy patois. What, plain english ain't good enough for 'em? Isn't it such a weird term though? Saying you're calling a function on a particular object seems clear enough. The term function has been around since the dawn of programming, so everyone knows what it means. Sure, it's not very OO, and someone - heaven forbid! - might think you're not all down with the objects. In that case, I am ok with "message." You send a message to a particular object. That's the smalltalk lingo, and it makes a certain amount of reasonable sense. It emphasizes the behaviour of objects over the idea of calling a function which manipulates data. Plus is has that OO cachet. When you talk about sending the hello_world message the person object, no one can look down on you as if you were some grubby C programmer, or worse, PHP! In a conversation with a coworker today, the only explanation I came up with was that if you were relying on &lt;span style="font-style: italic;"&gt;polymorphism&lt;/span&gt; (whoa, I am not even going to get into that mouthful today!) to do the right thing, then the particular &lt;span style="font-style: italic;"&gt;method of implementation of a given interface&lt;/span&gt; would depend on the subclass. So if you said the method of execution of a message on a particular object depends on the subclass, I wouldn't complain. It's long winded, but hey, it's ok. But if that's the idea, then what's "calling a method" all about? It just makes no sense to me! If that's the terminology you're going to use, well, just say "function." If you've made it this far, I'm impressed! :) Well, I don't know abou you, but I do feel better! And hey, if you're using "method" all over the place, don't feel too bad. When it comes down to it, so do I. As long as we're all drinking the coolaid together, it's all good.&lt;div class="blogger-post-footer"&gt;&lt;img width='1' height='1' src='https://blogger.googleusercontent.com/tracker/10784478-114843349048654506?l=vladimirlevin.blogspot.com' alt='' /&gt;&lt;/div&gt;</content><link rel='replies' type='application/atom+xml' href='http://vladimirlevin.blogspot.com/feeds/114843349048654506/comments/default' title='Post Comments'/><link rel='replies' type='text/html' href='http://www.blogger.com/comment.g?blogID=10784478&amp;postID=114843349048654506' title='0 Comments'/><link rel='edit' type='application/atom+xml' href='http://www.blogger.com/feeds/10784478/posts/default/114843349048654506'/><link rel='self' type='application/atom+xml' href='http://www.blogger.com/feeds/10784478/posts/default/114843349048654506'/><link rel='alternate' type='text/html' href='http://vladimirlevin.blogspot.com/2006/05/mindless-ranting.html' title='Mindless Ranting'/><author><name>Vladimir Levin</name><uri>http://www.blogger.com/profile/09680919094932667147</uri><email>noreply@blogger.com</email><gd:image rel='http://schemas.google.com/g/2005#thumbnail' width='21' height='32' src='http://2.bp.blogspot.com/_zD5Hp0u_Wi0/SqSQJLR_0_I/AAAAAAAAADE/l8j4ET6y63E/S220/vlad_korean.jpg'/></author><thr:total>0</thr:total></entry><entry><id>tag:blogger.com,1999:blog-10784478.post-114792296550235468</id><published>2006-05-17T20:15:00.000-07:00</published><updated>2006-10-21T07:41:51.143-07:00</updated><title type='text'>What Is Good Code?</title><content type='html'>I've noticed that it's somewhat easier to deal with poorly written procedural code than poorly written object-oriented code. The reason, I think, is that the procedural code is all together in large unwieldy functions full of repeated conditional logic. One can take that kind of code and break it up into smaller functions, and then organize those functions into classes. Then one can take duplicate code and just call the appropriate methods instead. It's not necessarily easy, true, but it tends to be easier than cleaning up a confusing bunch of objects and factories. Often the code duplication in object code is hidden so it takes quite a while to figure out how the code currently works, and where the duplications starts and ends; rather surprisingly, it's also more difficult to figure out how to refactor the code to a better model. I think one potential reason that object code becomes problematic is that developers who are less experienced with OO tend to try to make their code "object-oriented." The approach I would recommend focuses on function rather than form. Consider paying attention to two qualities:&lt;br /&gt;&lt;ol&gt;&lt;li&gt;Is your code easy to follow?&lt;br /&gt;&lt;/li&gt;&lt;li&gt;Do you have to make changes in several different places when modifying or extending your code?&lt;/li&gt;&lt;/ol&gt;Focusing on these items, making the code clear and removing duplication, ought to naturally lead to nice clean object-oriented code.&lt;div class="blogger-post-footer"&gt;&lt;img width='1' height='1' src='https://blogger.googleusercontent.com/tracker/10784478-114792296550235468?l=vladimirlevin.blogspot.com' alt='' /&gt;&lt;/div&gt;</content><link rel='replies' type='application/atom+xml' href='http://vladimirlevin.blogspot.com/feeds/114792296550235468/comments/default' title='Post Comments'/><link rel='replies' type='text/html' href='http://www.blogger.com/comment.g?blogID=10784478&amp;postID=114792296550235468' title='1 Comments'/><link rel='edit' type='application/atom+xml' href='http://www.blogger.com/feeds/10784478/posts/default/114792296550235468'/><link rel='self' type='application/atom+xml' href='http://www.blogger.com/feeds/10784478/posts/default/114792296550235468'/><link rel='alternate' type='text/html' href='http://vladimirlevin.blogspot.com/2006/05/what-is-good-code.html' title='What Is Good Code?'/><author><name>Vladimir Levin</name><uri>http://www.blogger.com/profile/09680919094932667147</uri><email>noreply@blogger.com</email><gd:image rel='http://schemas.google.com/g/2005#thumbnail' width='21' height='32' src='http://2.bp.blogspot.com/_zD5Hp0u_Wi0/SqSQJLR_0_I/AAAAAAAAADE/l8j4ET6y63E/S220/vlad_korean.jpg'/></author><thr:total>1</thr:total></entry><entry><id>tag:blogger.com,1999:blog-10784478.post-114757639574023257</id><published>2006-05-13T20:06:00.000-07:00</published><updated>2006-10-21T07:41:51.085-07:00</updated><title type='text'>Developing Stories</title><content type='html'>Based on experiences on my current project, I felt I had something to say about how to write stories. A story should be short. A story should have a clear purpose that can be demo'd to a user on its own. If two aspects of the story can demo'd separately, then there is a good chance they should each be defined as a separate story. One should not throw in unrelated bits and pieces into a story - "Oh and while you're at it, do this here." I was spending some time thinking about how to clearly justify and explain these opinions of mine. Luckily, now I don't really have to: Brian Marick seems to have mostly done the job for me: &lt;a href="http://www.exampler.com/writing/product-director.pdf"&gt;http://www.exampler.com/writing/product-director.pdf&lt;/a&gt;&lt;br /&gt;&lt;br /&gt;By the way, one idea that was introduced on my current project is excellent, and I'm not sure it's a standard agile practice. If not, it should be: The Demo. Each story should be demo'd briefly to the user when it has been completed. This practice insures that nothing significant is missing or misunderstood and tightens the feedback loop. The demo should be brief, no more than 5 or 10 minutes, and it should not include too many people - we had some problems with that in the beginning. Being able to demo a story to the user when it's been completed has proven to be both useful and simply satisfying for all concerned.&lt;div class="blogger-post-footer"&gt;&lt;img width='1' height='1' src='https://blogger.googleusercontent.com/tracker/10784478-114757639574023257?l=vladimirlevin.blogspot.com' alt='' /&gt;&lt;/div&gt;</content><link rel='replies' type='application/atom+xml' href='http://vladimirlevin.blogspot.com/feeds/114757639574023257/comments/default' title='Post Comments'/><link rel='replies' type='text/html' href='http://www.blogger.com/comment.g?blogID=10784478&amp;postID=114757639574023257' title='0 Comments'/><link rel='edit' type='application/atom+xml' href='http://www.blogger.com/feeds/10784478/posts/default/114757639574023257'/><link rel='self' type='application/atom+xml' href='http://www.blogger.com/feeds/10784478/posts/default/114757639574023257'/><link rel='alternate' type='text/html' href='http://vladimirlevin.blogspot.com/2006/05/developing-stories.html' title='Developing Stories'/><author><name>Vladimir Levin</name><uri>http://www.blogger.com/profile/09680919094932667147</uri><email>noreply@blogger.com</email><gd:image rel='http://schemas.google.com/g/2005#thumbnail' width='21' height='32' src='http://2.bp.blogspot.com/_zD5Hp0u_Wi0/SqSQJLR_0_I/AAAAAAAAADE/l8j4ET6y63E/S220/vlad_korean.jpg'/></author><thr:total>0</thr:total></entry><entry><id>tag:blogger.com,1999:blog-10784478.post-114757541785043001</id><published>2006-05-13T19:45:00.000-07:00</published><updated>2006-10-21T07:41:51.031-07:00</updated><title type='text'>Don't Get Me Wrong...</title><content type='html'>I actually like Ruby, I really do. It's become my favourite language for programming at home. One major annoyance I ran into today though has to do with the way booleans are implemented. The number 0 is evaluated as true. So the following actually prints!&lt;br /&gt;&lt;br /&gt;my_var = 0&lt;br /&gt;if (my_var)&lt;br /&gt;  printf("my_var evaluated as true?!")&lt;br /&gt;end&lt;br /&gt;&lt;br /&gt;As long as you're in the world of pure Ruby, this is ok, since you should really be writing 'my_var = false' anyway so the if statement behaves. However, databases generally implement booleans as ints. In fact, if you declare a field as a boolean in mysql, it really just creates a tinyint in the background. When you set that field to false in Rails, it ends up being set to '0' in the database, and then when you evaluate it in a condition, it behaves very unexpectedly, even though in the code, it really is being set to 'true'. You have to use the '?' operator to resolve the problem, e.g.&lt;br /&gt;&lt;br /&gt;if (my_active_record_object.flag_set?)&lt;br /&gt;printf("This works as expected\n")&lt;br /&gt;end&lt;br /&gt;&lt;br /&gt;if (my_active_record_object.flag_set)&lt;br /&gt;printf("This doesn't work as expected at all!\n")&lt;br /&gt;end&lt;br /&gt;&lt;br /&gt;It's a very insidious problem... This is one of those cases where I just kind of mentally shrug... WTF indeed!&lt;div class="blogger-post-footer"&gt;&lt;img width='1' height='1' src='https://blogger.googleusercontent.com/tracker/10784478-114757541785043001?l=vladimirlevin.blogspot.com' alt='' /&gt;&lt;/div&gt;</content><link rel='replies' type='application/atom+xml' href='http://vladimirlevin.blogspot.com/feeds/114757541785043001/comments/default' title='Post Comments'/><link rel='replies' type='text/html' href='http://www.blogger.com/comment.g?blogID=10784478&amp;postID=114757541785043001' title='0 Comments'/><link rel='edit' type='application/atom+xml' href='http://www.blogger.com/feeds/10784478/posts/default/114757541785043001'/><link rel='self' type='application/atom+xml' href='http://www.blogger.com/feeds/10784478/posts/default/114757541785043001'/><link rel='alternate' type='text/html' href='http://vladimirlevin.blogspot.com/2006/05/dont-get-me-wrong.html' title='Don&apos;t Get Me Wrong...'/><author><name>Vladimir Levin</name><uri>http://www.blogger.com/profile/09680919094932667147</uri><email>noreply@blogger.com</email><gd:image rel='http://schemas.google.com/g/2005#thumbnail' width='21' height='32' src='http://2.bp.blogspot.com/_zD5Hp0u_Wi0/SqSQJLR_0_I/AAAAAAAAADE/l8j4ET6y63E/S220/vlad_korean.jpg'/></author><thr:total>0</thr:total></entry><entry><id>tag:blogger.com,1999:blog-10784478.post-114460133235199799</id><published>2006-04-09T09:32:00.000-07:00</published><updated>2006-10-21T07:41:50.919-07:00</updated><title type='text'>More Observations about Ruby and Rails</title><content type='html'>I've been sick for the past few days and it's given me the opportunity to play around some more with test-driven development in rails. My overall conclusion is that ruby is a very interesting language, and the rails active-record approach looks very promising, but I am not sure I would  actually recommend this technology for a production system, at least not yet. Here are some pros and cons:&lt;br /&gt;&lt;br /&gt;Good points:&lt;br /&gt;&lt;ul&gt;&lt;li&gt;Ruby syntax is clear and simple, a joy to work with. The shortcuts for attributes, parenthesizing arguments to methods, passing in hashes as parameters, the simple use of 'end' to close blocks of code, and other such ideas really pop when you start using them.&lt;/li&gt;&lt;li&gt;Mixins seem to be a very nice compromise between the single inheritance of Java and the multiple-inheritance madness of C++. Again, the way they are implemented in Ruby is very nice and clean&lt;br /&gt;&lt;/li&gt;&lt;li&gt;The Rails active record pattern and the built-in testing framework encourages test-driven development and makes it very easy to develop a clear model. Mixins make it very easy for only the true domain-level code to show up in your model. The rest of the framework functionality is just there&lt;/li&gt;&lt;li&gt;Only database schema changes require rails to be restarted. Otherwise, you can make any change you want in the code and run the app! It's a vast improvement over JSP, that's for sure!&lt;br /&gt;&lt;/li&gt;&lt;/ul&gt;Weaknesses:&lt;br /&gt;&lt;ul&gt;&lt;li&gt;Running tests seems quite slow. 17 unit tests took 3.7 seconds on my 1.6MHz laptop with 512 MB  of RAM&lt;/li&gt;&lt;li&gt;I found that it seems as though rails might run each unit test concurrently which can cause weird problems if you are doing a lot of set up in your test rather than in the fixtures&lt;/li&gt;&lt;li&gt;So far there is no direct step-along-through-the-source-code debugging in any IDE as far as I can tell&lt;/li&gt;&lt;li&gt;So far there is no IDE-supported refactoring as there in Eclipse and Idea&lt;/li&gt;&lt;li&gt;Because Ruby is a dynamic language, even simple syntax errors are only identified at runtime. In practice, this means you &lt;span style="font-style: italic;"&gt;really &lt;/span&gt;have to write your code test-first. Even so, it is annoying to have to run tests just to find out that you forgot to pass in a parameter to a method.&lt;/li&gt;&lt;li&gt;I presume this is also because Ruby is dynamic, but as far as I know, there is no built-in code completion yet.&lt;br /&gt;&lt;/li&gt;&lt;li&gt;This is not necessarily the fault of Rails, but still, I have a feeling that many developers out there will end up putting a bunch of business logic right into the views and controllers.  This tends to be a problem in all languages and frameworks, with people simply not putting code in the domain where it belongs, so I don't know if it's fair to say it's a major fault of ruby, but nevertheless, I bet it will happen if Ruby and Rails take off&lt;/li&gt;&lt;li&gt;Having used them a bit, I don't know how I feel about blocks and closures. On one hand, they do let you effectively create domain-specific languages, e.g. see the Rake configuration. On the other hand, I have a feeling this kind of thing can easily be taken to dangerous extremes. &lt;/li&gt;&lt;/ul&gt;&lt;div class="blogger-post-footer"&gt;&lt;img width='1' height='1' src='https://blogger.googleusercontent.com/tracker/10784478-114460133235199799?l=vladimirlevin.blogspot.com' alt='' /&gt;&lt;/div&gt;</content><link rel='replies' type='application/atom+xml' href='http://vladimirlevin.blogspot.com/feeds/114460133235199799/comments/default' title='Post Comments'/><link rel='replies' type='text/html' href='http://www.blogger.com/comment.g?blogID=10784478&amp;postID=114460133235199799' title='2 Comments'/><link rel='edit' type='application/atom+xml' href='http://www.blogger.com/feeds/10784478/posts/default/114460133235199799'/><link rel='self' type='application/atom+xml' href='http://www.blogger.com/feeds/10784478/posts/default/114460133235199799'/><link rel='alternate' type='text/html' href='http://vladimirlevin.blogspot.com/2006/04/more-observations-about-ruby-and-rails.html' title='More Observations about Ruby and Rails'/><author><name>Vladimir Levin</name><uri>http://www.blogger.com/profile/09680919094932667147</uri><email>noreply@blogger.com</email><gd:image rel='http://schemas.google.com/g/2005#thumbnail' width='21' height='32' src='http://2.bp.blogspot.com/_zD5Hp0u_Wi0/SqSQJLR_0_I/AAAAAAAAADE/l8j4ET6y63E/S220/vlad_korean.jpg'/></author><thr:total>2</thr:total></entry><entry><id>tag:blogger.com,1999:blog-10784478.post-114322168440608873</id><published>2006-03-24T09:22:00.000-08:00</published><updated>2006-10-21T07:41:50.806-07:00</updated><title type='text'>Does Code Duplication Have To Be A Bad Thing?</title><content type='html'>This is a bit of a crazy idea. I'm curious what anyone reading this blog might think about it...&lt;br /&gt;&lt;br /&gt;The project I am currently working on validates the data coming from forms and imports in the domain. If you try to save a record with bad data in it, the domain will catch the error. The users also want irrelevant fields not to appear on the screen. A generic example would go something like this: Let's say you have a form which lets you enter a sales person's total sales for the month. If the sales exceed a certain threshold, then  you can enter in a bonus. The back end of the system validates the bonus. It makes sure that you are not allowed to enter a bonus if the total sales are too low. The customer also requests that the screen not show the entry field for the bonus if the sales entered are too low. There are a couple of options I can think of: In one case, you drive the screen code from the domain validation logic. Otherwise you can duplicate the logic, e.g.&lt;br /&gt;&lt;br /&gt;In the form code:&lt;br /&gt;&lt;br /&gt;if (totalSales &gt; MIN_BONUS_SALES) {&lt;br /&gt;  displayBonusField();&lt;br /&gt;&lt;br /&gt;} &lt;br /&gt;&lt;br /&gt;In the back-end domain code:&lt;br /&gt;&lt;br /&gt;if (totalSales &lt; MIN_BONUS_SALES) {&lt;br /&gt;  createNotEnoughSalesError();&lt;br /&gt;}&lt;br /&gt;&lt;br /&gt;This is bad because it means you have to maintain this logic in two places. What if the development environment allowed you to set up dependencies so you could still maintain the duplicate code, but the compiler would warn you if you changed code in one function and not the other? e.g.&lt;br /&gt;&lt;br /&gt;In the form code:&lt;br /&gt;&lt;br /&gt;@depends_on SalesPerson.validateBonus&lt;br /&gt;if (totalSales &gt; MIN_BONUS_SALES) {&lt;br /&gt;  displayBonusField();&lt;br /&gt;&lt;br /&gt;} &lt;br /&gt;&lt;br /&gt;In the back-end domain code:&lt;br /&gt;&lt;br /&gt;validateBonus() {&lt;br /&gt;&lt;br /&gt;  if (totalSales &lt; MIN_BONUS_SALES) {&lt;br /&gt;    createNotEnoughSalesError();&lt;br /&gt;  }&lt;br /&gt;}&lt;br /&gt;&lt;br /&gt;&lt;br /&gt;The point I'm making is that just updating both pieces of code isn't really a big problem, but knowing about all of the dependencies is. The normal way of dealing with it is to remove the dependencies and to develop a code framework that allows these ideas to be maintained in one place, but that can mean more work than one might want to do. I wonder if enabling tools to help manage code dependencies like this would be a viable option.&lt;div class="blogger-post-footer"&gt;&lt;img width='1' height='1' src='https://blogger.googleusercontent.com/tracker/10784478-114322168440608873?l=vladimirlevin.blogspot.com' alt='' /&gt;&lt;/div&gt;</content><link rel='replies' type='application/atom+xml' href='http://vladimirlevin.blogspot.com/feeds/114322168440608873/comments/default' title='Post Comments'/><link rel='replies' type='text/html' href='http://www.blogger.com/comment.g?blogID=10784478&amp;postID=114322168440608873' title='1 Comments'/><link rel='edit' type='application/atom+xml' href='http://www.blogger.com/feeds/10784478/posts/default/114322168440608873'/><link rel='self' type='application/atom+xml' href='http://www.blogger.com/feeds/10784478/posts/default/114322168440608873'/><link rel='alternate' type='text/html' href='http://vladimirlevin.blogspot.com/2006/03/does-code-duplication-have-to-be-bad.html' title='Does Code Duplication Have To Be A Bad Thing?'/><author><name>Vladimir Levin</name><uri>http://www.blogger.com/profile/09680919094932667147</uri><email>noreply@blogger.com</email><gd:image rel='http://schemas.google.com/g/2005#thumbnail' width='21' height='32' src='http://2.bp.blogspot.com/_zD5Hp0u_Wi0/SqSQJLR_0_I/AAAAAAAAADE/l8j4ET6y63E/S220/vlad_korean.jpg'/></author><thr:total>1</thr:total></entry><entry><id>tag:blogger.com,1999:blog-10784478.post-114153483706924938</id><published>2006-03-04T20:52:00.000-08:00</published><updated>2006-10-21T07:41:50.748-07:00</updated><title type='text'>Ruby and Rails</title><content type='html'>For the past few weeks I've been playing around with Ruby and Rails. I was somewhat hesitant at first, because I had heard such great things about Ruby and Rails. My natural reaction to that sort of effusive enthusiasm is to be skeptical. After all, the software development world seems to have an endless appetite for fads. Every time a new technology emerges, it promises to make programming easy and to solve the difficult problems that cause so many projects to fail, or at least to run into  serious delays and cost overruns. However, at present I must say that I am quite impressed. It really does seem to be such a nice clean framework, and it really is easy to do stuff. One of the things I like best about it so far is that my code doesn't have to be instrumented with a bunch of dependencies on the rails environment. I can write a pure ruby class and it will just work with rails. If I want to persist to a database, I can take advantage of the object-relational mapping, but the framework seems to do a great job of staying out of my way. It's not&lt;br /&gt;like J2EE where I can remember having to produce multitudes of classes and configuration data just to implement some trivial functionality. I am no expert on ruby or rails yet, but I must admit that I am pretty enthusiastic about the whole thing and hope to learn more as I go along.&lt;div class="blogger-post-footer"&gt;&lt;img width='1' height='1' src='https://blogger.googleusercontent.com/tracker/10784478-114153483706924938?l=vladimirlevin.blogspot.com' alt='' /&gt;&lt;/div&gt;</content><link rel='replies' type='application/atom+xml' href='http://vladimirlevin.blogspot.com/feeds/114153483706924938/comments/default' title='Post Comments'/><link rel='replies' type='text/html' href='http://www.blogger.com/comment.g?blogID=10784478&amp;postID=114153483706924938' title='0 Comments'/><link rel='edit' type='application/atom+xml' href='http://www.blogger.com/feeds/10784478/posts/default/114153483706924938'/><link rel='self' type='application/atom+xml' href='http://www.blogger.com/feeds/10784478/posts/default/114153483706924938'/><link rel='alternate' type='text/html' href='http://vladimirlevin.blogspot.com/2006/03/ruby-and-rails.html' title='Ruby and Rails'/><author><name>Vladimir Levin</name><uri>http://www.blogger.com/profile/09680919094932667147</uri><email>noreply@blogger.com</email><gd:image rel='http://schemas.google.com/g/2005#thumbnail' width='21' height='32' src='http://2.bp.blogspot.com/_zD5Hp0u_Wi0/SqSQJLR_0_I/AAAAAAAAADE/l8j4ET6y63E/S220/vlad_korean.jpg'/></author><thr:total>0</thr:total></entry><entry><id>tag:blogger.com,1999:blog-10784478.post-114108068525676212</id><published>2006-02-27T14:44:00.000-08:00</published><updated>2006-10-21T07:41:50.686-07:00</updated><title type='text'>TestDrivenDesignPhaseShift</title><content type='html'>This is rather belated news, but I am kind of proud of the fact that I've added a new term to the XP lexicon: Phase Shift. See the c2 wiki: &lt;br /&gt;&lt;a href="http://www.c2.com/cgi/wiki?TestDrivenDesignPhaseShift"&gt;&lt;br /&gt;http://www.c2.com/cgi/wiki?TestDrivenDesignPhaseShift&lt;/a&gt;. &lt;br /&gt;The notion came out of some discussions in the xp newsgroup. The basic idea is that even if you develop your code incrementally using test-driven development, it is possible that your approach may have to fundamentally change at some point. In my opinion, that's OK and does not confute xp and tdd as reasonable appraoches to develop software. Anyway, I was quite happy when I found out that someone had edited my initial posting to sound more definite and authoritative, and phase shift may well be a legitimate part of the xp lexicon now! :)&lt;div class="blogger-post-footer"&gt;&lt;img width='1' height='1' src='https://blogger.googleusercontent.com/tracker/10784478-114108068525676212?l=vladimirlevin.blogspot.com' alt='' /&gt;&lt;/div&gt;</content><link rel='replies' type='application/atom+xml' href='http://vladimirlevin.blogspot.com/feeds/114108068525676212/comments/default' title='Post Comments'/><link rel='replies' type='text/html' href='http://www.blogger.com/comment.g?blogID=10784478&amp;postID=114108068525676212' title='0 Comments'/><link rel='edit' type='application/atom+xml' href='http://www.blogger.com/feeds/10784478/posts/default/114108068525676212'/><link rel='self' type='application/atom+xml' href='http://www.blogger.com/feeds/10784478/posts/default/114108068525676212'/><link rel='alternate' type='text/html' href='http://vladimirlevin.blogspot.com/2006/02/testdrivendesignphaseshift.html' title='TestDrivenDesignPhaseShift'/><author><name>Vladimir Levin</name><uri>http://www.blogger.com/profile/09680919094932667147</uri><email>noreply@blogger.com</email><gd:image rel='http://schemas.google.com/g/2005#thumbnail' width='21' height='32' src='http://2.bp.blogspot.com/_zD5Hp0u_Wi0/SqSQJLR_0_I/AAAAAAAAADE/l8j4ET6y63E/S220/vlad_korean.jpg'/></author><thr:total>0</thr:total></entry><entry><id>tag:blogger.com,1999:blog-10784478.post-113985491503927151</id><published>2006-02-13T10:21:00.000-08:00</published><updated>2006-10-21T07:41:50.629-07:00</updated><title type='text'>Simple Refactoring</title><content type='html'>Refactoring doesn't have to be, and generally should not be, a complex and time-consuming activity. By using some simple refactoring practices it is possible to greatly simplify code and save time for other people reading the code in question. Here is an example:&lt;br /&gt;&lt;br /&gt;Here is the refactored code for calculating the number of hours remaining in the month:&lt;br /&gt;&lt;br /&gt;&lt;font face="arial"&gt;&lt;br /&gt;public static int calculateNumberOfRemainingHoursInMonthFromDate(Date fromDate) {&lt;br /&gt;    return hoursBetween(startOfNextMonth(fromDate), startOfDay(fromDate));&lt;br /&gt;}&lt;br /&gt;&lt;br /&gt;And here is the original code:&lt;br /&gt;&lt;br /&gt;public static int calculateNumberOfRemainingHoursInMonthFromDate(Date fromDate) {&lt;br /&gt;    Calendar startCal = Calendar.getInstance();&lt;br /&gt;    startCal.setTime(fromDate);&lt;br /&gt;    int startDay = startCal.get(Calendar.DAY_OF_MONTH);&lt;br /&gt;    int maxHoursInMonth = 0;&lt;br /&gt;    Calendar calendar = Calendar.getInstance();&lt;br /&gt;    calendar.setTime(fromDate);&lt;br /&gt;&lt;br /&gt;    calendar.set(Calendar.SECOND, calendar.getMinimum(Calendar.SECOND));&lt;br /&gt;    calendar.set(Calendar.MINUTE, calendar.getMinimum(Calendar.MINUTE));&lt;br /&gt;    calendar.set(Calendar.HOUR_OF_DAY,&lt;br /&gt;                 calendar.getMinimum(Calendar.HOUR_OF_DAY));&lt;br /&gt;    calendar.set(Calendar.DAY_OF_MONTH, startDay);&lt;br /&gt;    Date startDate = calendar.getTime();&lt;br /&gt;&lt;br /&gt;    calendar.add(Calendar.MONTH, 1);&lt;br /&gt;    calendar.set(Calendar.DAY_OF_MONTH, 1);&lt;br /&gt;    Date endDate = calendar.getTime();&lt;br /&gt;&lt;br /&gt;    long milliseconds = endDate.getTime() - startDate.getTime();&lt;br /&gt;    maxHoursInMonth = (int) (milliseconds / 1000 / 60 / 60);&lt;br /&gt;&lt;br /&gt;    maxHoursInMonth = correctHoursForAprilTo720(maxHoursInMonth);&lt;br /&gt;&lt;br /&gt;    return maxHoursInMonth;&lt;br /&gt;    }&lt;br /&gt;&lt;br /&gt;Below are the utility functions used in the refactored code:&lt;br /&gt;&lt;br /&gt;private static int hoursBetween(Date endDate, Date startDate) &lt;br /&gt;    long millisecondsRemainingInMonth = endDate.getTime() - &lt;br /&gt;    startDate.getTime();&lt;br /&gt;    int hoursRemainingInMonth = &lt;br /&gt;(int) (millisecondsRemainingInMonth / 1000 / 60 / 60);&lt;br /&gt;    hoursRemainingInMonth = correctHoursForAprilTo720(hoursRemainingInMonth);&lt;br /&gt;    return hoursRemainingInMonth;&lt;br /&gt;}&lt;br /&gt;&lt;br /&gt;private static Date startOfNextMonth(Date date) {&lt;br /&gt;    Date initializedDate = startOfDay(date);&lt;br /&gt;    Calendar toDateCalendar = Calendar.getInstance();&lt;br /&gt;    toDateCalendar.setTime(initializedDate);&lt;br /&gt;    toDateCalendar.add(Calendar.MONTH, 1);&lt;br /&gt;    toDateCalendar.set(Calendar.DAY_OF_MONTH, 1);&lt;br /&gt;    return toDateCalendar.getTime();&lt;br /&gt;}&lt;br /&gt;&lt;br /&gt;private static Date startOfDay(Date date) {&lt;br /&gt;    Calendar cal = Calendar.getInstance();&lt;br /&gt;    cal.setTime(date);&lt;br /&gt;    cal.set(Calendar.SECOND, cal.getMinimum(Calendar.SECOND));&lt;br /&gt;    cal.set(Calendar.MINUTE, cal.getMinimum(Calendar.MINUTE));&lt;br /&gt;    cal.set(Calendar.HOUR_OF_DAY, cal.getMinimum(Calendar.HOUR_OF_DAY));&lt;br /&gt;    Date startDate = cal.getTime();&lt;br /&gt;    return startDate;&lt;br /&gt;}&lt;br /&gt;&lt;/font&gt;&lt;div class="blogger-post-footer"&gt;&lt;img width='1' height='1' src='https://blogger.googleusercontent.com/tracker/10784478-113985491503927151?l=vladimirlevin.blogspot.com' alt='' /&gt;&lt;/div&gt;</content><link rel='replies' type='application/atom+xml' href='http://vladimirlevin.blogspot.com/feeds/113985491503927151/comments/default' title='Post Comments'/><link rel='replies' type='text/html' href='http://www.blogger.com/comment.g?blogID=10784478&amp;postID=113985491503927151' title='0 Comments'/><link rel='edit' type='application/atom+xml' href='http://www.blogger.com/feeds/10784478/posts/default/113985491503927151'/><link rel='self' type='application/atom+xml' href='http://www.blogger.com/feeds/10784478/posts/default/113985491503927151'/><link rel='alternate' type='text/html' href='http://vladimirlevin.blogspot.com/2006/02/simple-refactoring.html' title='Simple Refactoring'/><author><name>Vladimir Levin</name><uri>http://www.blogger.com/profile/09680919094932667147</uri><email>noreply@blogger.com</email><gd:image rel='http://schemas.google.com/g/2005#thumbnail' width='21' height='32' src='http://2.bp.blogspot.com/_zD5Hp0u_Wi0/SqSQJLR_0_I/AAAAAAAAADE/l8j4ET6y63E/S220/vlad_korean.jpg'/></author><thr:total>0</thr:total></entry><entry><id>tag:blogger.com,1999:blog-10784478.post-113299520870752988</id><published>2005-11-26T00:32:00.000-08:00</published><updated>2006-10-21T07:41:50.513-07:00</updated><title type='text'>Clearing The Fog: Strategy For Spikes to Clean Up Code</title><content type='html'>I've been working on quite a large project since February. It's hard to believe that it's been just about 10 months already. Such a project, with 20-30 developers, is quite different in nature from the smaller projects I've been involved with before. For one thing, one has less control over the code. People of varying abilities and inclinations are submitting code all the time, so --to borrow Fred Brooks' idiom-- maintaining conceptual integrity is a more difficult proposition. As such it is not unusual to run into less than optimal code in the application. The problem is that while I may sense bad smells in the code, in the midst of all the complexity it can be difficult to ascertain exactly what I should do about it. In some cases, I've found that simply trying out various refactorings just isn't as helpful as one might hope. One strategy I've found helpful is to start a completely new codebase and to quickly write some very simple code to model the functionality in question. That way I am not burdened with the production code base. I write the code test-first in order to generate what I think is a reasonable solution to the problem. Often I can get working tests and a reasonable sense of what the solution I want looks like much more quickly than I could by working on the production code base.I consider this to be a spike, but on our project, most people refer to a spike as an experiment applied to the production code. Once I've found a solution that seems to fit, I try to adapt it to the actual project. Often I can refactor reasonably large parts of the, ummm, less than optimal code, to match the general layout of my new solution to the problem. Sometimes I have to re-write some parts entirely. In any case, I've found that doing this kind of spike, away from the production code entirely, can help to quickly generate a fresh view of the problem and its solution.&lt;br /&gt;&lt;br /&gt;I had a look at the definition for a "spike" on the c2 Wiki and came upon concepts that appear basically identical to what I've described in this post:&lt;br /&gt;&lt;br /&gt;&lt;a href="http://www.c2.com/cgi/wiki?ClearTheFog"&gt;http://www.c2.com/cgi/wiki?ClearTheFog&lt;/a&gt;&lt;br /&gt;&lt;a href="http://www.c2.com/cgi/wiki?SpikeSolution"&gt;http://www.c2.com/cgi/wiki?SpikeSolution&lt;/a&gt;&lt;div class="blogger-post-footer"&gt;&lt;img width='1' height='1' src='https://blogger.googleusercontent.com/tracker/10784478-113299520870752988?l=vladimirlevin.blogspot.com' alt='' /&gt;&lt;/div&gt;</content><link rel='replies' type='application/atom+xml' href='http://vladimirlevin.blogspot.com/feeds/113299520870752988/comments/default' title='Post Comments'/><link rel='replies' type='text/html' href='http://www.blogger.com/comment.g?blogID=10784478&amp;postID=113299520870752988' title='0 Comments'/><link rel='edit' type='application/atom+xml' href='http://www.blogger.com/feeds/10784478/posts/default/113299520870752988'/><link rel='self' type='application/atom+xml' href='http://www.blogger.com/feeds/10784478/posts/default/113299520870752988'/><link rel='alternate' type='text/html' href='http://vladimirlevin.blogspot.com/2005/11/clearing-fog-strategy-for-spikes-to.html' title='Clearing The Fog: Strategy For Spikes to Clean Up Code'/><author><name>Vladimir Levin</name><uri>http://www.blogger.com/profile/09680919094932667147</uri><email>noreply@blogger.com</email><gd:image rel='http://schemas.google.com/g/2005#thumbnail' width='21' height='32' src='http://2.bp.blogspot.com/_zD5Hp0u_Wi0/SqSQJLR_0_I/AAAAAAAAADE/l8j4ET6y63E/S220/vlad_korean.jpg'/></author><thr:total>0</thr:total></entry><entry><id>tag:blogger.com,1999:blog-10784478.post-111768385517631760</id><published>2005-06-01T20:32:00.000-07:00</published><updated>2006-10-21T07:41:50.461-07:00</updated><title type='text'>Problem Solving and Avoidance</title><content type='html'>Today a colleague asked me for my take on a problem he was working on. He was trying to keep track of allocations for a given network of facilities. So for a particular facility, say an oil well, the allocation result would store the path that the oil took through various facilities. A more concrete example: Oil Sales Allocation, from Battery B2  to Well W1: W1 &lt;- B1 &lt;- B2. His approach at the database level was to store each segment of the path is a database record and to connect the top record to an allocation result record. The problem he was running into was how to match up a path to an allocation result. So suppose I know a given allocation was supposed to follow the path W1 &lt;- B1 &lt;- B2, how to I find the matching allocation in a reasonably efficient way. I suggested that he try something simpler to start with: Just store the allocation path as a string inside of an allocation record. That way, it's easy to match up the expected path with the actual path. If something more normalized becomes required at the database level, one can always use some PL/SQL (we're using Oracle) to create the needed string from a more complex database structure. He walked away with some enthusiasm for the idea. Now, we'll see if this particular idea actually works out in practice, but the point is that if you're running into a tough problem, the simplest approach might be to think of ways to avoid having to solve it altogether. It doesn't always work, but I have found this sort of approach to be a useful way of simplifying problems and therefore the corresponding design.&lt;div class="blogger-post-footer"&gt;&lt;img width='1' height='1' src='https://blogger.googleusercontent.com/tracker/10784478-111768385517631760?l=vladimirlevin.blogspot.com' alt='' /&gt;&lt;/div&gt;</content><link rel='replies' type='application/atom+xml' href='http://vladimirlevin.blogspot.com/feeds/111768385517631760/comments/default' title='Post Comments'/><link rel='replies' type='text/html' href='http://www.blogger.com/comment.g?blogID=10784478&amp;postID=111768385517631760' title='0 Comments'/><link rel='edit' type='application/atom+xml' href='http://www.blogger.com/feeds/10784478/posts/default/111768385517631760'/><link rel='self' type='application/atom+xml' href='http://www.blogger.com/feeds/10784478/posts/default/111768385517631760'/><link rel='alternate' type='text/html' href='http://vladimirlevin.blogspot.com/2005/06/problem-solving-and-avoidance.html' title='Problem Solving and Avoidance'/><author><name>Vladimir Levin</name><uri>http://www.blogger.com/profile/09680919094932667147</uri><email>noreply@blogger.com</email><gd:image rel='http://schemas.google.com/g/2005#thumbnail' width='21' height='32' src='http://2.bp.blogspot.com/_zD5Hp0u_Wi0/SqSQJLR_0_I/AAAAAAAAADE/l8j4ET6y63E/S220/vlad_korean.jpg'/></author><thr:total>0</thr:total></entry><entry><id>tag:blogger.com,1999:blog-10784478.post-111135726903306098</id><published>2005-03-20T14:14:00.000-08:00</published><updated>2006-10-21T07:41:50.408-07:00</updated><title type='text'>Rapid Convergence</title><content type='html'>In agile development, the customers decide which features to implement and when to implement those features. In XP the customers organize this information in the form of story cards. Each story card is assigned a priority and reflects a feature with real value to the business. I've found however that ordering features strictly by business priority may cause thrashing in the design of the code. So, while I still consider business priority to be a very important criterion for selecting what to work on, I also have come to think that technical people should be involved in making these kinds of decisions. In particular, I believe that with some thought, feature development can be organized to encourage rapid convergence of the code. In other words, one should try to avoid a situation in which one starts building a particular piece of functionality which stays in the system for a long time and becomes embedded in the design only to introduce something much later which requires that design to be completely overhauled.&lt;br /&gt;&lt;br /&gt;Now, that doesn't mean that one should make the mistake of developing a very general kind of design right from the start, the so called Big Design Up Front (BDUF). However, I think that customers and developers can work together to organize stories to maximize convergence. By convergence, I simply mean that the design of the system accomodates new stories so that their introduction is relatively routine and doesn't require a lot of re-design. As an example (without going into detail), the application I am currently working on handles many different "allocation methods." However, only now are we implementing stories that define more complex topological scenarios, i.e. "This thing which used to connect only to one other thing, now connects to many." From my point of view, this kind of situation represents a example of an opportunity to enhance convergence: Develop the application with just one allocation method, but make sure all of the topological issues are handled early on.&lt;br /&gt;&lt;br /&gt;In conclusion, iterative development is the best way to develop an application and BDUF in almost all cases is truly a bad idea. The design should indeed continue to evolve as a software development effort continues. However, by judiciously setting priorities on stories, one can encourage the design to crystallize more quickly.&lt;div class="blogger-post-footer"&gt;&lt;img width='1' height='1' src='https://blogger.googleusercontent.com/tracker/10784478-111135726903306098?l=vladimirlevin.blogspot.com' alt='' /&gt;&lt;/div&gt;</content><link rel='replies' type='application/atom+xml' href='http://vladimirlevin.blogspot.com/feeds/111135726903306098/comments/default' title='Post Comments'/><link rel='replies' type='text/html' href='http://www.blogger.com/comment.g?blogID=10784478&amp;postID=111135726903306098' title='0 Comments'/><link rel='edit' type='application/atom+xml' href='http://www.blogger.com/feeds/10784478/posts/default/111135726903306098'/><link rel='self' type='application/atom+xml' href='http://www.blogger.com/feeds/10784478/posts/default/111135726903306098'/><link rel='alternate' type='text/html' href='http://vladimirlevin.blogspot.com/2005/03/rapid-convergence.html' title='Rapid Convergence'/><author><name>Vladimir Levin</name><uri>http://www.blogger.com/profile/09680919094932667147</uri><email>noreply@blogger.com</email><gd:image rel='http://schemas.google.com/g/2005#thumbnail' width='21' height='32' src='http://2.bp.blogspot.com/_zD5Hp0u_Wi0/SqSQJLR_0_I/AAAAAAAAADE/l8j4ET6y63E/S220/vlad_korean.jpg'/></author><thr:total>0</thr:total></entry><entry><id>tag:blogger.com,1999:blog-10784478.post-111008988651868078</id><published>2005-03-05T21:57:00.000-08:00</published><updated>2006-10-21T07:41:50.351-07:00</updated><title type='text'>The KISS Principle</title><content type='html'>As software development continues its mad pursuit of new ideas and paradigms, whether it's about Design Patterns, Refactoring, Aspect-Oriented programming, or something else, people's tendency to forget about the basics of good programming continues to be a source of constant frustration for me. Of all of the software development principles and heuristics, the one I consider to be the most fundamental is the KISS principle: Keep It Simple, Stupid!&lt;br /&gt;&lt;br /&gt;Good programming means keeping functions small. I've learned to adhere to Christian Pekeler's idea that one should try to limit functions to 6 lines of code. In working with this idea together with TDD, I've been surprised at how strong the effect on the design is. It's a simple idea indeed, but a powerful one!&lt;br /&gt;&lt;br /&gt;Another basic principle I value highly is to remove duplication. If adding or modifying functionality has you poking around in many different places there's something wrong. Don't wait for it to get worse. Fix it now. It doesn't make sense to allow things to deteriorate to the point where working with the code becomes painful. It's easy to fix problems of duplication early; fixing them once they become truly painful is hard because by then the code has become inflexible. This wonderfully simple and useful idea leads the design patterns emerge naturally in the code rather than forcing them into existence by force of an architect's will.&lt;br /&gt;&lt;br /&gt;So, is there anything wrong with Object-Oriented Programming? Design Patterns? Architectural Patterns? Aspect-Oriented Programming, or what have you? All of these ideas are presented by intelligent people genuinely trying to make a contribution, but all too often developers forget about the KISS principle and the basics of good programming.&lt;br /&gt;&lt;br /&gt;&lt;span style="font-style: italic;"&gt;&lt;blockquote&gt;Agile Developers are dedicated to keeping the design as appropriate and clean as possible. This is not a haphazard or tentative commitment. Agile Developers do not "clean up" the design every few weeks. Rather, they keep the software a clean, simple, and expressive as they possibly can, every day, every hour, and even every minute. They never say, "We'll go back and fix that later." They never let the rot begin. -- Robert C Martin, Agile Software Development.&lt;br /&gt;&lt;/blockquote&gt;&lt;/span&gt;&lt;div class="blogger-post-footer"&gt;&lt;img width='1' height='1' src='https://blogger.googleusercontent.com/tracker/10784478-111008988651868078?l=vladimirlevin.blogspot.com' alt='' /&gt;&lt;/div&gt;</content><link rel='replies' type='application/atom+xml' href='http://vladimirlevin.blogspot.com/feeds/111008988651868078/comments/default' title='Post Comments'/><link rel='replies' type='text/html' href='http://www.blogger.com/comment.g?blogID=10784478&amp;postID=111008988651868078' title='0 Comments'/><link rel='edit' type='application/atom+xml' href='http://www.blogger.com/feeds/10784478/posts/default/111008988651868078'/><link rel='self' type='application/atom+xml' href='http://www.blogger.com/feeds/10784478/posts/default/111008988651868078'/><link rel='alternate' type='text/html' href='http://vladimirlevin.blogspot.com/2005/03/kiss-principle.html' title='The KISS Principle'/><author><name>Vladimir Levin</name><uri>http://www.blogger.com/profile/09680919094932667147</uri><email>noreply@blogger.com</email><gd:image rel='http://schemas.google.com/g/2005#thumbnail' width='21' height='32' src='http://2.bp.blogspot.com/_zD5Hp0u_Wi0/SqSQJLR_0_I/AAAAAAAAADE/l8j4ET6y63E/S220/vlad_korean.jpg'/></author><thr:total>0</thr:total></entry><entry><id>tag:blogger.com,1999:blog-10784478.post-110902146473517466</id><published>2005-02-21T13:04:00.000-08:00</published><updated>2006-10-21T07:41:50.192-07:00</updated><title type='text'>Variations on TDD</title><content type='html'>TDD is the cornerstone of XP. TDD requires one to write tests ahead of code. The basics of TDD are laid out in books by Kent Beck (Test Driven Development By Example) and others. However, as time has gone by and XP has evolved, it appears as though different ideas about how to write code test-first have emerged, all claiming to be TDD. Since I am a strong advocate of XP and TDD, I thought I'd lay out some of these variations I've seen in the wild:&lt;br /&gt;&lt;br /&gt;&lt;ol&gt;      &lt;li&gt;Traditional TDD: Development is done one simple test at a time. Refactoring is applied frequently at a small scale. One starts with an intentionally naive design and allows the addition of new tests to guide the evolving design to greater levels of complexity. One can do some up front thinking about a problem, including brainstorming, using diagrams or crc cards, but the focus is to keep the design as simple as possible with each new test&lt;/li&gt;   &lt;li&gt;Proactive TDD: Proactive TDD is similar to traditional TDD in that one uses small-scale tests. However, one generally develops a fairly established design ahead of time and the tests are written to realize that design. This approach is less flexible than traditional TDD, but the feedback cycle is still short and provides the opportunity to re-think the design if it looks as though it is going in the wrong direction.&lt;/li&gt;&lt;li&gt;End-To-End TDD: In this variation, one does not write small-scale tests. Instead one starts off working with what are essentially acceptance tests: High level tests that cover the execution of code for a story or a substantial part of a story. Such tests may use something like the FIT framework or they may involve calling a high level API inside of xUnit. To make one test pass, quite a bit of code must be written through all the layers of the application. The presumed goal of this approach is to avoid having to modify many small tests as the application logic changes. The drawback is that this is not really a good design technique since one cannot apply a short test-code-refactor cycle. Overall I would say this approach discourages frequent refactoring and leads to low quality code. If one does decide use this approach, In my opinion one should be prepared to do a lot of careful design up front.&lt;/li&gt;&lt;li&gt;Mock-Driven Development: I am unfamiliar with this approach, but there appears to be a school of developers who produce even more granular tests with the extensive use of mock objects. The sense I get is that this kind of development is perhaps more similar to Design By Contract and ties tests very closely to the implementation details of an API. So far I can't evaluate this method, but I have to admit that I am biased in favour of testing state before and after a test rather than worrying about the actual calls made.&lt;br /&gt;&lt;/li&gt;   &lt;/ol&gt; Based on my experience thus far, I consider Traditional TDD to be the best approach in most cases and Proactive TDD to be acceptable in some cases. I believe that all in all traditional TDD minimizes the risk of ending up with unmanageable code. While I am a strong supporter of acceptance tests, I believe that all application code should be developed using a short test-code-refactor cycle, and therefore one should use traditional TDD techniques to write the code that will eventually make the acceptance test pass. Without the traditional TDD, one loses the ability to frequently refactor the code in small chunks and to get a good sense of its overall effect on the design.&lt;div class="blogger-post-footer"&gt;&lt;img width='1' height='1' src='https://blogger.googleusercontent.com/tracker/10784478-110902146473517466?l=vladimirlevin.blogspot.com' alt='' /&gt;&lt;/div&gt;</content><link rel='replies' type='application/atom+xml' href='http://vladimirlevin.blogspot.com/feeds/110902146473517466/comments/default' title='Post Comments'/><link rel='replies' type='text/html' href='http://www.blogger.com/comment.g?blogID=10784478&amp;postID=110902146473517466' title='0 Comments'/><link rel='edit' type='application/atom+xml' href='http://www.blogger.com/feeds/10784478/posts/default/110902146473517466'/><link rel='self' type='application/atom+xml' href='http://www.blogger.com/feeds/10784478/posts/default/110902146473517466'/><link rel='alternate' type='text/html' href='http://vladimirlevin.blogspot.com/2005/02/variations-on-tdd.html' title='Variations on TDD'/><author><name>Vladimir Levin</name><uri>http://www.blogger.com/profile/09680919094932667147</uri><email>noreply@blogger.com</email><gd:image rel='http://schemas.google.com/g/2005#thumbnail' width='21' height='32' src='http://2.bp.blogspot.com/_zD5Hp0u_Wi0/SqSQJLR_0_I/AAAAAAAAADE/l8j4ET6y63E/S220/vlad_korean.jpg'/></author><thr:total>0</thr:total></entry><entry><id>tag:blogger.com,1999:blog-10784478.post-110844241544614662</id><published>2005-02-14T20:37:00.000-08:00</published><updated>2006-10-21T07:41:50.140-07:00</updated><title type='text'>Appropriate Metaphor For Software Engineering</title><content type='html'>Jeanette Winterson is one of my favourite writers, especially her novel The Passion. This is from the monthly column she writes for her Web site:&lt;br /&gt;&lt;blockquote&gt;My friend Mona Howard, who is 84, told me she had been to see the film Touching The Void, about the mountaineers, one of whom makes an incredible survival journey with a broken leg. He got through it by &lt;i&gt;setting himself only what he could achieve without agony giving way to despair&lt;/i&gt;. So he would hop for twenty minutes, then rest, then hop again.&lt;br /&gt;&lt;/blockquote&gt;:-)&lt;div class="blogger-post-footer"&gt;&lt;img width='1' height='1' src='https://blogger.googleusercontent.com/tracker/10784478-110844241544614662?l=vladimirlevin.blogspot.com' alt='' /&gt;&lt;/div&gt;</content><link rel='replies' type='application/atom+xml' href='http://vladimirlevin.blogspot.com/feeds/110844241544614662/comments/default' title='Post Comments'/><link rel='replies' type='text/html' href='http://www.blogger.com/comment.g?blogID=10784478&amp;postID=110844241544614662' title='1 Comments'/><link rel='edit' type='application/atom+xml' href='http://www.blogger.com/feeds/10784478/posts/default/110844241544614662'/><link rel='self' type='application/atom+xml' href='http://www.blogger.com/feeds/10784478/posts/default/110844241544614662'/><link rel='alternate' type='text/html' href='http://vladimirlevin.blogspot.com/2005/02/appropriate-metaphor-for-software.html' title='Appropriate Metaphor For Software Engineering'/><author><name>Vladimir Levin</name><uri>http://www.blogger.com/profile/09680919094932667147</uri><email>noreply@blogger.com</email><gd:image rel='http://schemas.google.com/g/2005#thumbnail' width='21' height='32' src='http://2.bp.blogspot.com/_zD5Hp0u_Wi0/SqSQJLR_0_I/AAAAAAAAADE/l8j4ET6y63E/S220/vlad_korean.jpg'/></author><thr:total>1</thr:total></entry><entry><id>tag:blogger.com,1999:blog-10784478.post-110823223732998533</id><published>2005-02-12T10:01:00.000-08:00</published><updated>2006-10-21T07:41:50.059-07:00</updated><title type='text'>What makes a successful XP team?</title><content type='html'>I've recently had the experience of working with a productive team and I thought I'd share the characteristics that I believe were important to its success at delivering on time with a low defect rate:&lt;br /&gt;&lt;ul&gt;&lt;li&gt;Avoid politics: Everyone on the team was always thinking of ways to improve the quality of the product and the code. There was no sense that people were motivated because they were trying to impress a boss.&lt;br /&gt;&lt;/li&gt;&lt;br /&gt;&lt;li&gt;Do not over-engineer: The focus was on getting results, not on stroking one's ego or on doing software engineering for its own sake. All too often in the OO world, I see over-engineered code that seems to be developed out of some desire to be clever or to copy something from a book.&lt;br /&gt;&lt;/li&gt;&lt;br /&gt;&lt;li&gt;Remain critical: There was a strong desire to root out problems in the design. In other words developers did not fall in love with their designs, regarded the code critically, and were eager to make changes to improve it.&lt;/li&gt;&lt;br /&gt;&lt;li&gt;Allow some slack: Developers were able to negotiate periods of time to focus on cleaning up the design of the application rather than pushing forward with user stories. Sometimes it is necessary to go in and thoroughly clean up, especially when dealing with a legacy codebase.&lt;br /&gt;&lt;/li&gt;&lt;br /&gt;&lt;li&gt;Maintain discipline: Discipline and focus was very good. Planning was done in 2 week sprints and people were not getting constantly interrupted during a sprint. One could count on the estimates provided for stories.&lt;/li&gt;&lt;br /&gt;&lt;li&gt;Have a separate QA group: A separate QA group producing automated end-to-end tests was very useful. Together, the end-to-end tests produced by QA and the more granular tests produced by the developers provided a high degree of confidence in the code and allowed fairly significant refactorings to be done.&lt;br /&gt;&lt;/li&gt; &lt;br /&gt;&lt;li&gt;Promote a team culture: Developers maintained high morale by taking an easy-going approach to the project, even at times of high pressure. On our team, the developers and QA people played video games at lunch and during the last half-hour of the day. Any kind of activity along these lines promotes a sense of team-identity. Whatever it might be, it is a good idea to come up with something non-work related the team can do together on a regular basis.&lt;br /&gt;&lt;/li&gt;&lt;br /&gt;&lt;/ul&gt;&lt;div class="blogger-post-footer"&gt;&lt;img width='1' height='1' src='https://blogger.googleusercontent.com/tracker/10784478-110823223732998533?l=vladimirlevin.blogspot.com' alt='' /&gt;&lt;/div&gt;</content><link rel='replies' type='application/atom+xml' href='http://vladimirlevin.blogspot.com/feeds/110823223732998533/comments/default' title='Post Comments'/><link rel='replies' type='text/html' href='http://www.blogger.com/comment.g?blogID=10784478&amp;postID=110823223732998533' title='0 Comments'/><link rel='edit' type='application/atom+xml' href='http://www.blogger.com/feeds/10784478/posts/default/110823223732998533'/><link rel='self' type='application/atom+xml' href='http://www.blogger.com/feeds/10784478/posts/default/110823223732998533'/><link rel='alternate' type='text/html' href='http://vladimirlevin.blogspot.com/2005/02/what-makes-successful-xp-team.html' title='What makes a successful XP team?'/><author><name>Vladimir Levin</name><uri>http://www.blogger.com/profile/09680919094932667147</uri><email>noreply@blogger.com</email><gd:image rel='http://schemas.google.com/g/2005#thumbnail' width='21' height='32' src='http://2.bp.blogspot.com/_zD5Hp0u_Wi0/SqSQJLR_0_I/AAAAAAAAADE/l8j4ET6y63E/S220/vlad_korean.jpg'/></author><thr:total>0</thr:total></entry></feed>
