<?xml version="1.0" encoding="UTF-8"?>
<?xml-stylesheet type="text/xsl" media="screen" href="/~d/styles/atom10full.xsl"?><?xml-stylesheet type="text/css" media="screen" href="http://feeds.feedburner.com/~d/styles/itemcontent.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:feedburner="http://rssnamespace.org/feedburner/ext/1.0"><id>tag:blogger.com,1999:blog-652174954000901332</id><updated>2009-10-13T02:50:07.579+01:00</updated><title type="text">Øyvind Valland's Babel Lutefisk .net</title><subtitle type="html">[bey-buhl loo-tuh-fisk] : A distant relative of the Babel Fish. Recognisable by it's glassy eyes and incomprehensible jabbering.</subtitle><link rel="http://schemas.google.com/g/2005#feed" type="application/atom+xml" href="http://www.babel-lutefisk.net/feeds/posts/default" /><link rel="alternate" type="text/html" href="http://www.babel-lutefisk.net/" /><link rel="hub" href="http://pubsubhubbub.appspot.com/" /><link rel="next" type="application/atom+xml" href="http://www.blogger.com/feeds/652174954000901332/posts/default?start-index=26&amp;max-results=25" /><author><name>Øyvind Valland</name><uri>http://www.blogger.com/profile/17595718624373482981</uri><email>noreply@blogger.com</email></author><generator version="7.00" uri="http://www.blogger.com">Blogger</generator><openSearch:totalResults>53</openSearch:totalResults><openSearch:startIndex>1</openSearch:startIndex><openSearch:itemsPerPage>25</openSearch:itemsPerPage><link rel="self" href="http://feeds.feedburner.com/BabelLutefisk" type="application/atom+xml" /><feedburner:emailServiceId>BabelLutefisk</feedburner:emailServiceId><feedburner:feedburnerHostname>http://feedburner.google.com</feedburner:feedburnerHostname><atom10:link xmlns:atom10="http://www.w3.org/2005/Atom" rel="hub" href="http://pubsubhubbub.appspot.com" /><entry><id>tag:blogger.com,1999:blog-652174954000901332.post-1527660273534997975</id><published>2009-09-28T18:26:00.002+01:00</published><updated>2009-09-28T18:36:10.171+01:00</updated><title type="text">Literate Programming</title><content type="html">A while back I wrote &lt;a href="http://www.babel-lutefisk.net/2009/03/names-and-importance-of-semantics.html"&gt;a rather lengthy entry about the significance of strong and clear naming conventions&lt;/a&gt;, and I spent some time explaining how well-defined, unambiguously named methods with to-the-point parameter names end up reading like sentences out of a book.&lt;br /&gt;&lt;br /&gt;Today &lt;a href="http://eugoogoolizer.blogspot.com/"&gt;a friend&lt;/a&gt; pointed me to the &lt;a href="http://www.literateprogramming.com/index.html"&gt;Literate Programming website&lt;/a&gt;, where the following snippet can be found:&lt;br /&gt;&lt;br /&gt;"I believe that the time is ripe for significantly better documentation of programs, and that we can best achieve this by considering programs to be works of literature. Hence, my title: 'Literate Programming.'&lt;br /&gt;&lt;br /&gt;Let us change our traditional attitude to the construction of programs: Instead of imagining that our main task is to instruct a computer what to do, let us concentrate rather on explaining to human beings what we want a computer to do.&lt;br /&gt;&lt;br /&gt;The practitioner of literate programming can be regarded as an essayist, whose main concern is with exposition and excellence of style. Such an author, with thesaurus in hand, chooses the names of variables carefully and explains what each variable means. He or she strives for a program that is comprehensible because its concepts have been introduced in an order that is best for human understanding, using a mixture of formal and informal methods that reinforce each other."&lt;br /&gt;&lt;br /&gt;When I read this I immediately thought: YES! This is exactly what I've been trying to say. Code should not be a language for a select 'elite' that prides itself on obscurity. It should be something that can be read with ease and even by someone with very little technical understanding. I dare say that if you achieve that, you've achieved maintainable code.&lt;div class="blogger-post-footer"&gt;&lt;img width='1' height='1' src='https://blogger.googleusercontent.com/tracker/652174954000901332-1527660273534997975?l=www.babel-lutefisk.net'/&gt;&lt;/div&gt;&lt;img src="http://feeds.feedburner.com/~r/BabelLutefisk/~4/Tn3jun8VxBM" height="1" width="1"/&gt;</content><link rel="replies" type="application/atom+xml" href="http://www.babel-lutefisk.net/feeds/1527660273534997975/comments/default" title="Post Comments" /><link rel="replies" type="text/html" href="https://www.blogger.com/comment.g?blogID=652174954000901332&amp;postID=1527660273534997975" title="0 Comments" /><link rel="edit" type="application/atom+xml" href="http://www.blogger.com/feeds/652174954000901332/posts/default/1527660273534997975" /><link rel="self" type="application/atom+xml" href="http://www.blogger.com/feeds/652174954000901332/posts/default/1527660273534997975" /><link rel="alternate" type="text/html" href="http://feedproxy.google.com/~r/BabelLutefisk/~3/Tn3jun8VxBM/literate-programming.html" title="Literate Programming" /><author><name>Øyvind Valland</name><uri>http://www.blogger.com/profile/17595718624373482981</uri><email>noreply@blogger.com</email><gd:extendedProperty xmlns:gd="http://schemas.google.com/g/2005" name="OpenSocialUserId" value="18377601055500046677" /></author><thr:total xmlns:thr="http://purl.org/syndication/thread/1.0">0</thr:total><feedburner:origLink>http://www.babel-lutefisk.net/2009/09/literate-programming.html</feedburner:origLink></entry><entry><id>tag:blogger.com,1999:blog-652174954000901332.post-6980128326618987584</id><published>2009-09-23T12:29:00.001+01:00</published><updated>2009-09-23T12:31:06.776+01:00</updated><title type="text">Boolean Polymorphism</title><content type="html">I think &lt;a href="http://eugoogoolizer.blogspot.com/2009/09/boolean-polymorphism.html"&gt;this is a rather good article&lt;/a&gt; about the pitfalls of large parameter lists and code maintainability.&lt;div class="blogger-post-footer"&gt;&lt;img width='1' height='1' src='https://blogger.googleusercontent.com/tracker/652174954000901332-6980128326618987584?l=www.babel-lutefisk.net'/&gt;&lt;/div&gt;&lt;img src="http://feeds.feedburner.com/~r/BabelLutefisk/~4/6qUQo8XyYlE" height="1" width="1"/&gt;</content><link rel="replies" type="application/atom+xml" href="http://www.babel-lutefisk.net/feeds/6980128326618987584/comments/default" title="Post Comments" /><link rel="replies" type="text/html" href="https://www.blogger.com/comment.g?blogID=652174954000901332&amp;postID=6980128326618987584" title="0 Comments" /><link rel="edit" type="application/atom+xml" href="http://www.blogger.com/feeds/652174954000901332/posts/default/6980128326618987584" /><link rel="self" type="application/atom+xml" href="http://www.blogger.com/feeds/652174954000901332/posts/default/6980128326618987584" /><link rel="alternate" type="text/html" href="http://feedproxy.google.com/~r/BabelLutefisk/~3/6qUQo8XyYlE/boolean-polymorphism.html" title="Boolean Polymorphism" /><author><name>Øyvind Valland</name><uri>http://www.blogger.com/profile/17595718624373482981</uri><email>noreply@blogger.com</email><gd:extendedProperty xmlns:gd="http://schemas.google.com/g/2005" name="OpenSocialUserId" value="18377601055500046677" /></author><thr:total xmlns:thr="http://purl.org/syndication/thread/1.0">0</thr:total><feedburner:origLink>http://www.babel-lutefisk.net/2009/09/boolean-polymorphism.html</feedburner:origLink></entry><entry><id>tag:blogger.com,1999:blog-652174954000901332.post-3136633895546715579</id><published>2009-07-22T08:39:00.001+01:00</published><updated>2009-07-22T10:23:45.905+01:00</updated><title type="text">Factory Assembly Lines, Red Cars, and TDD</title><content type="html">For the last five weeks I have been supporting developers on a project that makes full use of automated unit and integration tests, including the use of a mocking framework. The frameworks of choice are NUnit and Moq, which is fairly standard stuff. What makes our little project special, though, is that the developers were all (bar one) completely new to the concepts of unit testing and mocking! This has made for some interesting challenges. All the developers are highly capable and intelligent people, so they've adopted the new principles with amazing speed. But as anyone who's transitioned to TDD will know, the mindset required is very different from that of 'traditional' development. As such, I've had to do a lot of mentoring during the last month or so.&lt;br /&gt;&lt;br /&gt;There's nothing quite like having a good example to go by when you're trying to learn something new. That's the case with TDD as well. I also think that in order to learn TDD and the test-first discipline you need something more. What's needed is a school of thought. Perhaps even a dogma. I think that this is far more important than specific examples of how to do specific things, because with the correct line of thinking you'll arrive at good solutions to any of your testing problems. It was with this in mind that I wrote what follows; a rather absurd testing scenario involving a factory assembly line and lots of red cars.&lt;br /&gt;&lt;br /&gt;What I want to address now is the creation of tests, and the scope of this discussion includes what a test should test (the scope of the test, if you like), where boundaries should be drawn, and how such decisions should influence your design while you’re coding. For now, imagine that you are responsible for the production line of cars, and that you want to be able to test that a car is painted in the colour that you have specified.&lt;br /&gt;&lt;br /&gt;How would you go about testing such a thing? The first thing that springs to mind is perhaps to instruct your assembly line (people and machines) to build you a red car, and then go have a look at the car when it’s built to see if it is, in fact, red. Such an approach would certainly work, but it would be a hell of an expensive test! What if the car came out the wrong colour? Or a different shade of red than you expected? You’d have to keep cranking out cars while making adjustments until you get the colour right, and that’s just not a sensible approach. &lt;br /&gt;&lt;br /&gt;Of course, this example is absurd because you would never do that if you owned a car factory – but I’ve chosen this example exactly for that reason; you’re clearly doing too much work just to check that the car turns out with the right colour. Too much work. That’s a key thing to remember.&lt;br /&gt;&lt;br /&gt;How could you improve on the process? Well, you might start by skipping the entire “build-me-a-car” bit and focus on the paint job itself. A car is painted by a big robot with lots of paint guns, and this whole mess takes place at the end when the car has been assembled and all non-metallic surfaces have been carefully masked etc. Since this is where paint is applied we can narrow our testing to this machine. We can put a piece of paper in front of the paint gun and ask it to colour the paper red. If things turn out unexpectedly, we can easily repeat the test. Paper is cheap, and even paint is much cheaper than a car. Not only that, but repeating the test is much faster also. This test is therefore infinitely better than the first test. We’re doing much less work, it’s costing less, and we’ve focused right down on the thing that makes a car red (or any other colour). Focus. That’s another key thing to remember.&lt;br /&gt;&lt;br /&gt;Let’s stop and think about focus for a moment. In the first test, if a car turned out burgundy rather than the sports-car red you’d imagined, where would you make your adjustments before testing again? Sure, you may know that it’s the big ol’ paint robot at the end of the line that does the work, but how do you get your instructions to it? Is there a human involved? At what stage of the car assembly do you have to ‘input’ the colour? Right at the start? Does anything happen to your colour instruction while the car is being built? Does one human tell another, or is it written down on paper and later typed into a computer? It should be fairly easy to see that a test with such wide focus (or no focus at all) is prone to all kinds of environmental noise that can affect the output and thus make accurate testing difficult. So focus is important.&lt;br /&gt;&lt;br /&gt;Now, we’ve narrowed our focus to the robot that paints the car, and we’ve devised a test that involves the robot spraying paint onto a sheet of paper. This is, in the scheme of things, probably a decent test. But we can do better. Does the paint gun produce the colour? No it doesn’t. The purpose of the paint gun is to deliver paint at the correct pressure and velocity, and to ensure that the nozzle produces a mist of paint with exactly the right droplet size etc. We can certainly  use the paint gun to test colour, but since it’s got nothing to do with producing the colour of paint, we should see if we can create a better test. We should narrow our focus again.&lt;br /&gt;&lt;br /&gt;If you keep repeating the process of narrowing your focus you’ll eventually end up at the part of the machine that mixes paint to create specific colours. Now the focus seems to be about right (you can probably narrow things down even further, though). The part of the machine that mixes the paint is what’s responsible for the colour that eventually ends up on the car. Arguably, you can take the whole paint element out of it because your paint is likely to be generic and colourless – so you can just focus on the mixing of pigments. But I don’t want to be too pedantic, either.&lt;br /&gt;&lt;br /&gt;Now that we’ve got the focus right, we’ve got to get our test right. We’re trying to verify that when we ask for red, red is what we get. But if you think about it, red isn’t very specific either. Is it blood red? Burgundy? Maroon? A bit more on the pink side of the spectrum? To try and test for red isn’t specific enough. And here’s another thing to be mindful of. Be specific. Don’t test for red, but instead test for a specific shade of red. And so your test will start to change shape as well. Rather than testing for a colour you’ll find that you’ll be testing that the paint mixer dispenses the correct amounts of red, green, and blue (the basic components of the RGB colour system) in order to produce a specific shade of a specific colour. Now you’ve got a good test. A valuable test. A test you can write home about.&lt;br /&gt;&lt;br /&gt;Such a test can be carried out without much work, it’s focused (it involves only part of a sub-system), and it’s very specific (it tests conditions for very specific input). All these things are good. In the context of the car factory you’ve now got a fast, cheap, repeatable, and accurate test that’ll verify that your factory is capable of cranking out cars in every colour of the spectrum.&lt;br /&gt;&lt;br /&gt;Well, that’s actually a half truth. Or less than a half truth. You’ve only created a test for mixing pigments. You’ve not tested that the right amount of mixed pigment is added to the correct volume of paint. Nor have you tested that the paint gun actually works like it should and that the paint-robot moves like it should. And there isn’t a single test, yet, for any other aspect of the car assembly line. All this is beyond the scope of this discussion, but suffice to say that if you are a car producer hell-bent on making big bucks you’d apply the same principles as above to creating tests for every single aspect of your production line.&lt;br /&gt;&lt;br /&gt;Now let’s try and relate this example back to software. The car assembly line would likely be implemented as a number of applications and/or services that each carry out specific tasks (basic assembly, welding, engine installation etc). The paint-robot might be one such application. The robot’s paint gun would be represented by a class, as would the pigment mixer. And the actual mixing of pigments would probably be represented as a single method on the pigment mixer class. That’s the unit you’d be testing. You wouldn’t write a test that invokes all those applications because it would require too much work and be too difficult, and it would result in an inherently inaccurate test.&lt;br /&gt;&lt;br /&gt;So, when you’re writing tests and designing your code you should always make sure that what you’re working on lends itself to testing (it doesn’t require a lot of work), it is focused, and very specific. If what you are testing is part of something much, much larger then ensure that your unit is isolated. You do this by using mock objects for its dependencies. If you can’t use mock objects for whatever reason you should stop and think about why that is and see if you can change your design. Maybe you don’t have to. Maybe you can run your test in a slightly wider context without doing too much work or becoming too unfocused or non-specific. If you can, fine. If you can’t – change your design.&lt;br /&gt;&lt;br /&gt;Careful thinking about how you’d test the code you are going to write will help you write better systems. As with anything, it requires practice and experience (and you’ll never stop learning) and it’s possible to go terribly wrong – but if every decision you make is the result of careful, informed consideration the likelihood of failure is minimal. Good tests are tests that are focused on one system, and specifically a single function of that one system – and that do very little work in order to test that function. Make the creation of such tests your goal, and you’ll quickly learn how to write clean, robust, and testable code.&lt;div class="blogger-post-footer"&gt;&lt;img width='1' height='1' src='https://blogger.googleusercontent.com/tracker/652174954000901332-3136633895546715579?l=www.babel-lutefisk.net'/&gt;&lt;/div&gt;&lt;img src="http://feeds.feedburner.com/~r/BabelLutefisk/~4/bC4AQ_s2ZB0" height="1" width="1"/&gt;</content><link rel="replies" type="application/atom+xml" href="http://www.babel-lutefisk.net/feeds/3136633895546715579/comments/default" title="Post Comments" /><link rel="replies" type="text/html" href="https://www.blogger.com/comment.g?blogID=652174954000901332&amp;postID=3136633895546715579" title="0 Comments" /><link rel="edit" type="application/atom+xml" href="http://www.blogger.com/feeds/652174954000901332/posts/default/3136633895546715579" /><link rel="self" type="application/atom+xml" href="http://www.blogger.com/feeds/652174954000901332/posts/default/3136633895546715579" /><link rel="alternate" type="text/html" href="http://feedproxy.google.com/~r/BabelLutefisk/~3/bC4AQ_s2ZB0/factory-assembly-lines-red-cars-and-tdd.html" title="Factory Assembly Lines, Red Cars, and TDD" /><author><name>Øyvind Valland</name><uri>http://www.blogger.com/profile/17595718624373482981</uri><email>noreply@blogger.com</email><gd:extendedProperty xmlns:gd="http://schemas.google.com/g/2005" name="OpenSocialUserId" value="18377601055500046677" /></author><thr:total xmlns:thr="http://purl.org/syndication/thread/1.0">0</thr:total><feedburner:origLink>http://www.babel-lutefisk.net/2009/07/factory-assembly-lines-red-cars-and-tdd.html</feedburner:origLink></entry><entry><id>tag:blogger.com,1999:blog-652174954000901332.post-7409740332116860753</id><published>2009-06-22T11:25:00.002+01:00</published><updated>2009-06-22T11:30:34.220+01:00</updated><title type="text">PartCover - an alternative to NCover?</title><content type="html">I've been looking for a cheap or free tool for measuring NUnit test coverage and just stumbled upon &lt;a href="http://sourceforge.net/projects/partcover/"&gt;PartCover&lt;/a&gt;. I've installed it and fiddled with it and it seems to be an OK tool. It's Open Source, too - which I think is great.&lt;br /&gt;&lt;br /&gt;I have to say, though, that the documentation is poor and the application itself is buggy (I experienced a critical exception when trying to save a coverage report to file). Despite this, I'll take a buggy PartCover over NCover which would set me back $650 for a license! &lt;br /&gt;&lt;br /&gt;Might write more about this later. Check it out!&lt;div class="blogger-post-footer"&gt;&lt;img width='1' height='1' src='https://blogger.googleusercontent.com/tracker/652174954000901332-7409740332116860753?l=www.babel-lutefisk.net'/&gt;&lt;/div&gt;&lt;img src="http://feeds.feedburner.com/~r/BabelLutefisk/~4/0GlP0cmwe_o" height="1" width="1"/&gt;</content><link rel="replies" type="application/atom+xml" href="http://www.babel-lutefisk.net/feeds/7409740332116860753/comments/default" title="Post Comments" /><link rel="replies" type="text/html" href="https://www.blogger.com/comment.g?blogID=652174954000901332&amp;postID=7409740332116860753" title="0 Comments" /><link rel="edit" type="application/atom+xml" href="http://www.blogger.com/feeds/652174954000901332/posts/default/7409740332116860753" /><link rel="self" type="application/atom+xml" href="http://www.blogger.com/feeds/652174954000901332/posts/default/7409740332116860753" /><link rel="alternate" type="text/html" href="http://feedproxy.google.com/~r/BabelLutefisk/~3/0GlP0cmwe_o/partcover-alternative-to-ncover.html" title="PartCover - an alternative to NCover?" /><author><name>Øyvind Valland</name><uri>http://www.blogger.com/profile/17595718624373482981</uri><email>noreply@blogger.com</email><gd:extendedProperty xmlns:gd="http://schemas.google.com/g/2005" name="OpenSocialUserId" value="18377601055500046677" /></author><thr:total xmlns:thr="http://purl.org/syndication/thread/1.0">0</thr:total><feedburner:origLink>http://www.babel-lutefisk.net/2009/06/partcover-alternative-to-ncover.html</feedburner:origLink></entry><entry><id>tag:blogger.com,1999:blog-652174954000901332.post-3868202232761648336</id><published>2009-03-13T11:12:00.002Z</published><updated>2009-03-13T11:29:05.089Z</updated><title type="text">Names and the Importance of Semantics</title><content type="html">I've taken the below 'post' from some documentation I've recently written for the developers where I'm currently working. It appears to me that, in general, developers (and, indeed, architects) spend far too little time thinking about names and naming conventions. Personally I spend &lt;span style="font-style:italic;"&gt;hours&lt;/span&gt; thinking about names. Good names are an &lt;span style="font-style:italic;"&gt;incredibly&lt;/span&gt; important aspect of good software design. Anyway - if you care to read on, this is what I've said on the subject so far:&lt;br /&gt;&lt;br /&gt;Aside from writing code that is correct, efficient, and actually works, the most important aspect of software development is, arguably, naming. Choosing good names for namespaces, classes, methods, and properties (even member variables, local variables and parameters) is incrediby important (and therefore also difficult) because the semantics they convey. A name must be unambiguous and clearly convey the purpose and function of the named component when viewed in isolation, as well as when it is viewed in the context of its root namespace, immediate namespace, class, and so on.&lt;br /&gt;&lt;br /&gt;Good type and namespace names leave little room for misunderstandings and mistakes because of ambiguity. Namespaces and types defined in the .NET Framework are very clearly named throughout and the semantics of each name are typically very clear. A good example of this is the &lt;code&gt;System.IO&lt;/code&gt; namespace.&lt;br /&gt;&lt;br /&gt;The &lt;code&gt;System.IO&lt;/code&gt; namespace name is unambiguous because it is short, because the relationship between the components of the namespace ("System" and "IO") is clear, and because each component of the namespace is named well semantically:&lt;br /&gt;&lt;br /&gt;"System" implies a logical grouping of functionality that is 'close to the machine' or 'close to the framework'. The "System" namespace, by virtue of its name, is very clearly not a task or application specific namespace. &lt;br /&gt;&lt;br /&gt;While it may be argued that the word "System" is ambigous because it can encapsulate so much functionality (and varied functionality at that), when seen in its context (it is the main root namespace of the entire framework) the name is still very clear.&lt;br /&gt;&lt;br /&gt;&lt;br /&gt;"IO" is a very old and commonly used abbreviation ("InputOutput") in computer science and is always associated with data transfer between devices (both internal and peripheral). The immediate association of "IO" is that of file read/write operations, and this is exactly the kind of functionality that the classes in this namespace provides.&lt;br /&gt;&lt;br /&gt;&lt;code&gt;System.IO&lt;/code&gt; is therefore a really good namespace because the semantics of the first component's name lends meaning to the other. "System" tells the developer that we're dealing with general, non application-specific functionality, and "IO" implies that the functionality is file-operation specific.&lt;br /&gt;&lt;br /&gt;The &lt;code&gt;File&lt;/code&gt; class within the &lt;code&gt;System.IO&lt;/code&gt; namespace is another good example of good naming. Its fully qualified name, &lt;code&gt;System.IO.File&lt;/code&gt;, makes it absolutely clear what the class is and what it does - it's very clearly a representation of a file on a file system and provides file operations to the caller.&lt;br /&gt;&lt;br /&gt;The methods on the &lt;code&gt;File&lt;/code&gt; class are also very well named. A couple of examples illustrate how clear, short names can convey a lot of information when viewed in their proper context:&lt;br /&gt;&lt;br /&gt;&lt;code&gt;public static System.IO.FileStream Open(string path, System.IO.FileMode mode)&lt;/code&gt;&lt;br /&gt;&lt;br /&gt;The method name &lt;code&gt;File.Open&lt;/code&gt; is in itself very clear; it is obvious that the &lt;code&gt;Open()&lt;/code&gt; method will open a file on a disk. There is sometimes a tendency to be too specific when naming methods - the above method might for example be called &lt;code&gt;OpenFile()&lt;/code&gt;. Viewed entirely in isolation, the second method name, &lt;code&gt;OpenFile()&lt;/code&gt;, is clearer than &lt;code&gt;Open()&lt;/code&gt; - but when viewed in the context of its class, &lt;code&gt;OpenFile()&lt;/code&gt; is obviously a poorer name than &lt;code&gt;Open()&lt;/code&gt; because the context (the &lt;code&gt;File&lt;/code&gt; class) already makes it obvious that we are in fact dealing with files!&lt;br /&gt;&lt;br /&gt;&lt;br /&gt;&lt;code&gt;public static bool Exists(string path)&lt;/code&gt;&lt;br /&gt;&lt;br /&gt;This method name is clear because it can be phrased as a question with a simple yes/no (or true/false) answer: "Does this file exist?" &lt;br /&gt;&lt;br /&gt;&lt;code&gt;public static void Move(string sourceFileName, string destFileName)&lt;/code&gt;&lt;br /&gt;&lt;br /&gt;This method name is unambiguous (clearly &lt;code&gt;File.Move()&lt;/code&gt; is a method that moves a file on a file system), but pay particular attention to the parameter names; &lt;code&gt;sourceFileName&lt;/code&gt; and &lt;code&gt;destFileName&lt;/code&gt; leave no doubt about what you are dealing with. If this method's signature is paraphrased into a sentence it would read something like "move this source file to this destination."&lt;br /&gt;&lt;br /&gt;The above examples above illustrate the importance of context when constructing names in software. A named element must make sense in isolation, but it is also very  important that it makes sense contextually. Methods must be named so that the name itself carries the correct semantics, but the method's parameters (and return type) should be named in a manner so as to add further semantic value to the method's signature.&lt;div class="blogger-post-footer"&gt;&lt;img width='1' height='1' src='https://blogger.googleusercontent.com/tracker/652174954000901332-3868202232761648336?l=www.babel-lutefisk.net'/&gt;&lt;/div&gt;&lt;img src="http://feeds.feedburner.com/~r/BabelLutefisk/~4/dFjNMlvBuC4" height="1" width="1"/&gt;</content><link rel="replies" type="application/atom+xml" href="http://www.babel-lutefisk.net/feeds/3868202232761648336/comments/default" title="Post Comments" /><link rel="replies" type="text/html" href="https://www.blogger.com/comment.g?blogID=652174954000901332&amp;postID=3868202232761648336" title="1 Comments" /><link rel="edit" type="application/atom+xml" href="http://www.blogger.com/feeds/652174954000901332/posts/default/3868202232761648336" /><link rel="self" type="application/atom+xml" href="http://www.blogger.com/feeds/652174954000901332/posts/default/3868202232761648336" /><link rel="alternate" type="text/html" href="http://feedproxy.google.com/~r/BabelLutefisk/~3/dFjNMlvBuC4/names-and-importance-of-semantics.html" title="Names and the Importance of Semantics" /><author><name>Øyvind Valland</name><uri>http://www.blogger.com/profile/17595718624373482981</uri><email>noreply@blogger.com</email><gd:extendedProperty xmlns:gd="http://schemas.google.com/g/2005" name="OpenSocialUserId" value="18377601055500046677" /></author><thr:total xmlns:thr="http://purl.org/syndication/thread/1.0">1</thr:total><feedburner:origLink>http://www.babel-lutefisk.net/2009/03/names-and-importance-of-semantics.html</feedburner:origLink></entry><entry><id>tag:blogger.com,1999:blog-652174954000901332.post-6567263821881354852</id><published>2009-03-10T22:23:00.003Z</published><updated>2009-03-10T22:25:14.902Z</updated><title type="text">Orange Mocha Frappucino</title><content type="html">This is just a quick note to those of you that I know read this blog - because I know you know Steve. He's started blogging over on &lt;a href="http://eugoogoolizer.blogspot.com/"&gt;Orange Mocha Frappucino&lt;/a&gt;. First post is about handling web.config in unit tests. Good one, Steve!&lt;div class="blogger-post-footer"&gt;&lt;img width='1' height='1' src='https://blogger.googleusercontent.com/tracker/652174954000901332-6567263821881354852?l=www.babel-lutefisk.net'/&gt;&lt;/div&gt;&lt;img src="http://feeds.feedburner.com/~r/BabelLutefisk/~4/gkOF0T2d6cc" height="1" width="1"/&gt;</content><link rel="replies" type="application/atom+xml" href="http://www.babel-lutefisk.net/feeds/6567263821881354852/comments/default" title="Post Comments" /><link rel="replies" type="text/html" href="https://www.blogger.com/comment.g?blogID=652174954000901332&amp;postID=6567263821881354852" title="0 Comments" /><link rel="edit" type="application/atom+xml" href="http://www.blogger.com/feeds/652174954000901332/posts/default/6567263821881354852" /><link rel="self" type="application/atom+xml" href="http://www.blogger.com/feeds/652174954000901332/posts/default/6567263821881354852" /><link rel="alternate" type="text/html" href="http://feedproxy.google.com/~r/BabelLutefisk/~3/gkOF0T2d6cc/orange-mocha-frappucino.html" title="Orange Mocha Frappucino" /><author><name>Øyvind Valland</name><uri>http://www.blogger.com/profile/17595718624373482981</uri><email>noreply@blogger.com</email><gd:extendedProperty xmlns:gd="http://schemas.google.com/g/2005" name="OpenSocialUserId" value="18377601055500046677" /></author><thr:total xmlns:thr="http://purl.org/syndication/thread/1.0">0</thr:total><feedburner:origLink>http://www.babel-lutefisk.net/2009/03/orange-mocha-frappucino.html</feedburner:origLink></entry><entry><id>tag:blogger.com,1999:blog-652174954000901332.post-289256828328827961</id><published>2009-02-24T12:44:00.002Z</published><updated>2009-02-24T12:56:18.546Z</updated><title type="text">James Joyce .NET</title><content type="html">Last week, after doing a code review, I coined the term "James Joyce .NET". Though the James Joyce factor isn't particularly .NET specific (I'm sure there are Ruby, C++, Java, and most certainly C developers out there who do things in similarly cryptic manners), I think the term has a nice ring to it. And in fairness to Joyce, I think the code I reviewed was far less readable than Ulysses.&lt;br /&gt;&lt;br /&gt;Aside from software that works and "does its thing" in a reliable manner, clients care a lot about code that's maintainable. The client may not &lt;span style="font-style:italic;"&gt;know&lt;/span&gt; that they care about this, at least not at first - but once you tell them that a change is going to take three weeks to complete "because of this, that, and the other" (because the code you've written isn't maintainable) you bet your sweet ass they start caring. They care not because of the state of your code; they care because of the cost. And rightly so.&lt;br /&gt;&lt;br /&gt;There are many key things to consider when writing maintainable code but the subject of my current rant will be &lt;span style="font-style:italic;"&gt;readability&lt;/span&gt;. Does your code read like a book? Probably not (hey, it's &lt;span style="font-style:italic;"&gt;not&lt;/span&gt; fiction) - and that's OK. But do your method names and signatures read like sentences? Could you translate the body of your methods into short little textual paragraphs that clearly illustrate what they do? If you answered "no" to both of these questions it's probably time to stop and think a little.&lt;br /&gt;&lt;br /&gt;&lt;span style="font-style:italic;"&gt;&lt;span style="font-weight:bold;"&gt;Disclaimer:&lt;/span&gt; I'm renowned for harping on about ideals and I've been caught out many a time falling short of my own mark. That said, I stick to my ideals because without them we've got nowhere to go.&lt;/span&gt;&lt;br /&gt;&lt;br /&gt;To start with, code must be legible. That means you have to choose names (for your classes, methods, parameters, variables) that clearly indicate purpose. Favour readability over brevity when creating names. Second, your names must make semantic sense. A class-method name combination should be completely unambiguous, easy to read, and clearly convey "what you get". Classes and methods should do what it says on the tin. Don't be obscure, don't be ambiguous.&lt;br /&gt;&lt;br /&gt;Third: Use the appropriate constructs for the job. Don't embed an algorithm in a property. Don't use private properties. Properties are there to &lt;span style="font-style:italic;"&gt;expose&lt;/span&gt; aspects of a class, so if you're not going to expose it, use a private member variable instead. Don't use indexers for anything but accessing collection data. Don't use generics unless you &lt;span style="font-style:italic;"&gt;need&lt;/span&gt; generic code, and then only if generics give you something that a typed parameter list doesn't (using interface/abstract classes instead of concrete types).&lt;br /&gt;&lt;br /&gt;Seriously, think long and hard about &lt;span style="font-style:italic;"&gt;any&lt;/span&gt; code you write. Just because something works doesn't make it good. And give some thought to those people that come after you. Will they be able to understand what you've done? You might very well be a genius and the best thing since sliced bread but really, what good is that if nobody understands what you've done? Don't obfuscate your code by being lazy, too clever, or by using constructs in a way that they were not intended.&lt;br /&gt;&lt;br /&gt;&amp;lt;/ rant&amp;gt;&lt;div class="blogger-post-footer"&gt;&lt;img width='1' height='1' src='https://blogger.googleusercontent.com/tracker/652174954000901332-289256828328827961?l=www.babel-lutefisk.net'/&gt;&lt;/div&gt;&lt;img src="http://feeds.feedburner.com/~r/BabelLutefisk/~4/W39AxKK0DQ4" height="1" width="1"/&gt;</content><link rel="replies" type="application/atom+xml" href="http://www.babel-lutefisk.net/feeds/289256828328827961/comments/default" title="Post Comments" /><link rel="replies" type="text/html" href="https://www.blogger.com/comment.g?blogID=652174954000901332&amp;postID=289256828328827961" title="0 Comments" /><link rel="edit" type="application/atom+xml" href="http://www.blogger.com/feeds/652174954000901332/posts/default/289256828328827961" /><link rel="self" type="application/atom+xml" href="http://www.blogger.com/feeds/652174954000901332/posts/default/289256828328827961" /><link rel="alternate" type="text/html" href="http://feedproxy.google.com/~r/BabelLutefisk/~3/W39AxKK0DQ4/james-joyce.html" title="James Joyce .NET" /><author><name>Øyvind Valland</name><uri>http://www.blogger.com/profile/17595718624373482981</uri><email>noreply@blogger.com</email><gd:extendedProperty xmlns:gd="http://schemas.google.com/g/2005" name="OpenSocialUserId" value="18377601055500046677" /></author><thr:total xmlns:thr="http://purl.org/syndication/thread/1.0">0</thr:total><feedburner:origLink>http://www.babel-lutefisk.net/2009/02/james-joyce.html</feedburner:origLink></entry><entry><id>tag:blogger.com,1999:blog-652174954000901332.post-5943086310072484216</id><published>2009-02-18T13:28:00.000Z</published><updated>2009-02-18T13:29:17.175Z</updated><title type="text">What not to do 5 minutes before a meeting...</title><content type="html">I typically don't read the &lt;a href="http://www.metro.co.uk/"&gt;Metro&lt;/a&gt; magazine on my way to work, but today I did. And there was a little snippet in there about a YouTube video that was supposed to be very funny. This tickled my curiousity, so when I found myself with a couple of minutes to spare before a meeting this morning, I went to YouTube to watch the clip about &lt;a href="http://www.youtube.com/watch?v=txqiwrbYGrs"&gt;David After Dentist&lt;/a&gt;.&lt;br /&gt;&lt;br /&gt;Bad decision. It took me a good 10 minutes to stop grinning and get my sudden bursts of laughter under control. Not good when someone's called a meeting with you to give you an update on serious matters.&lt;br /&gt;&lt;br /&gt;Funny as hell though :-)&lt;div class="blogger-post-footer"&gt;&lt;img width='1' height='1' src='https://blogger.googleusercontent.com/tracker/652174954000901332-5943086310072484216?l=www.babel-lutefisk.net'/&gt;&lt;/div&gt;&lt;img src="http://feeds.feedburner.com/~r/BabelLutefisk/~4/FM_76PKdKa4" height="1" width="1"/&gt;</content><link rel="replies" type="application/atom+xml" href="http://www.babel-lutefisk.net/feeds/5943086310072484216/comments/default" title="Post Comments" /><link rel="replies" type="text/html" href="https://www.blogger.com/comment.g?blogID=652174954000901332&amp;postID=5943086310072484216" title="0 Comments" /><link rel="edit" type="application/atom+xml" href="http://www.blogger.com/feeds/652174954000901332/posts/default/5943086310072484216" /><link rel="self" type="application/atom+xml" href="http://www.blogger.com/feeds/652174954000901332/posts/default/5943086310072484216" /><link rel="alternate" type="text/html" href="http://feedproxy.google.com/~r/BabelLutefisk/~3/FM_76PKdKa4/what-not-to-do-5-minutes-before-meeting.html" title="What not to do 5 minutes before a meeting..." /><author><name>Øyvind Valland</name><uri>http://www.blogger.com/profile/17595718624373482981</uri><email>noreply@blogger.com</email><gd:extendedProperty xmlns:gd="http://schemas.google.com/g/2005" name="OpenSocialUserId" value="18377601055500046677" /></author><thr:total xmlns:thr="http://purl.org/syndication/thread/1.0">0</thr:total><feedburner:origLink>http://www.babel-lutefisk.net/2009/02/what-not-to-do-5-minutes-before-meeting.html</feedburner:origLink></entry><entry><id>tag:blogger.com,1999:blog-652174954000901332.post-1772397627166916151</id><published>2008-11-13T21:32:00.004Z</published><updated>2008-11-13T21:44:30.210Z</updated><category scheme="http://www.blogger.com/atom/ns#" term="MVC" /><category scheme="http://www.blogger.com/atom/ns#" term="Testing" /><category scheme="http://www.blogger.com/atom/ns#" term="Quality" /><title type="text">Brittleware</title><content type="html">This is really just an observation, and a highly subjective one at that. To any die-hard ASP.NET traditionalist out there: This isn't meant as an attack, so don't take it as one.&lt;br /&gt;&lt;br /&gt;I've been working on the ASP.NET MVC framework together with my buddy Steve for a while now and we've been trying out a lot of different things while getting to grips with this new (and much better) way of doing things. We've been trying to establish our own patterns for developing MVC applications, and while doing so we have experimented and written a lot of code, and very few tests.&lt;br /&gt;&lt;br /&gt;During this phase of experimentation I truly came to love the MVC framework for its flexibility and elegance, but for some reason I had this nagging feeling that all was not well. It was a familiar feeling, too, and one that I associate specifically with web development. But I couldn't put my finger on it.&lt;br /&gt;&lt;br /&gt;Then just a couple of days ago I realised what it was. We'd decided to start building in earnest, and using the MVC framework in anger. Nothing would be written unless it was tested. And after a couple of hours of intense controller-testing I suddenly realised that the uneasy feeling was gone, and in its place was a feeling of security and contentment.&lt;br /&gt;&lt;br /&gt;What I'd felt before was the same feeling I always had when writing ASP.NET applications. Things just felt &lt;span style="font-style:italic;"&gt;brittle&lt;/span&gt; and ready to break. I could go to any length in order to ensure that the application did what it should, worked like intended, and would fail gracefully - but somehow that feeling of brittleness never went away completely. I didn't have any tests, no way of verifying that I was still on the right path, the straight and narrow. And writing MVC applications without tests gave me that same feeling because really, I was no better off.&lt;br /&gt;&lt;br /&gt;With the introduction of tests that feeling of brittleness disappeared and instead the application felt robust. Solid. Stable. Reliable. Add any number of synonyms. If you believe in TDD you know what I'm talking about.&lt;br /&gt;&lt;br /&gt;I don't know if there's a moral to this story, but the realisation I had has confirmed to me yet again how &lt;span style="font-style:italic;"&gt;correct&lt;/span&gt; it is to develop everything with tests first. There simply isn't another way.&lt;div class="blogger-post-footer"&gt;&lt;img width='1' height='1' src='https://blogger.googleusercontent.com/tracker/652174954000901332-1772397627166916151?l=www.babel-lutefisk.net'/&gt;&lt;/div&gt;&lt;img src="http://feeds.feedburner.com/~r/BabelLutefisk/~4/HQo7fWSBzHE" height="1" width="1"/&gt;</content><link rel="replies" type="application/atom+xml" href="http://www.babel-lutefisk.net/feeds/1772397627166916151/comments/default" title="Post Comments" /><link rel="replies" type="text/html" href="https://www.blogger.com/comment.g?blogID=652174954000901332&amp;postID=1772397627166916151" title="0 Comments" /><link rel="edit" type="application/atom+xml" href="http://www.blogger.com/feeds/652174954000901332/posts/default/1772397627166916151" /><link rel="self" type="application/atom+xml" href="http://www.blogger.com/feeds/652174954000901332/posts/default/1772397627166916151" /><link rel="alternate" type="text/html" href="http://feedproxy.google.com/~r/BabelLutefisk/~3/HQo7fWSBzHE/brittleware.html" title="Brittleware" /><author><name>Øyvind Valland</name><uri>http://www.blogger.com/profile/17595718624373482981</uri><email>noreply@blogger.com</email><gd:extendedProperty xmlns:gd="http://schemas.google.com/g/2005" name="OpenSocialUserId" value="18377601055500046677" /></author><thr:total xmlns:thr="http://purl.org/syndication/thread/1.0">0</thr:total><feedburner:origLink>http://www.babel-lutefisk.net/2008/11/brittleware.html</feedburner:origLink></entry><entry><id>tag:blogger.com,1999:blog-652174954000901332.post-7777887169958695703</id><published>2008-10-29T17:16:00.005Z</published><updated>2008-10-29T17:32:16.717Z</updated><title type="text">Ninject providers and Moq mock injection.</title><content type="html">A few months back I stumbled upon &lt;a href="http://www.ninject.org"&gt;Ninject&lt;/a&gt; while reading a post on &lt;a href="http://jonas.follesoe.no"&gt;Jonas Follesø's blog&lt;/a&gt;. Since then I've been busy architecting a very modular e-commerce solution for a client, and just recently have I started "tying the application together" using Ninject. Ninject makes for very simple dependency injection, indeed. The Ninject approach is so straight forward, in fact, that Ninject isn't just a good framework for Inversion of Control (IoC) - it's an excellent tool for teaching the principles of IoC as well.&lt;br /&gt;&lt;br /&gt;I'm not going to go into any detail on how to use Ninject here, though - &lt;a href="http://dojo.ninject.org/"&gt;there are lots of guides and tutorials in the Dojo&lt;/a&gt;.&lt;br /&gt;&lt;br /&gt;What I will talk about here, however, is a nice little solution for injecting mocked objects using a Ninject binding provider. My solution uses a Service Locator similar to the one Jonas sets out in his &lt;a href="http://jonas.follesoe.no/YouCardRevisitedImplementingDependencyInjectionInSilverlight.aspx"&gt;article on Silverlight and Ninject&lt;/a&gt;, but the focus here is on the binding providers and how to use them in a unit testing scenario. Nonetheless, a quick look at how the Service Locator is used will not go astray.&lt;br /&gt;&lt;br /&gt;&lt;code&gt;&lt;br /&gt;public class ServiceLocator&lt;br /&gt;{&lt;br /&gt; public IKernel Kernel { get; private set; }&lt;br /&gt;&lt;br /&gt; public static ServiceLocator Instance { get; private set; }&lt;br /&gt;&lt;br /&gt; public T Get&amp;lt;T&amp;gt;() { return Instance.Kernel.Get&amp;lt;T&amp;gt;(); }&lt;br /&gt;&lt;br /&gt; public ServiceLocator(params IModule[] modules)&lt;br /&gt; {&lt;br /&gt;  Kernel = new StandardKernel(modules);&lt;br /&gt;  Instance = this;&lt;br /&gt; }&lt;br /&gt;}&lt;br /&gt;&lt;/code&gt;&lt;br /&gt;&lt;br /&gt;As you can see, the ServiceLocator class is a singleton. You load it up once for your application, and classes can happily use it to get access to instances of types defined by an interface, such as &lt;br /&gt;&lt;br /&gt;&lt;code&gt;&lt;br /&gt;ICategoryService svc = ServiceLocator.Instance.Get&amp;lt;ICategoryService&amp;gt;();&lt;br /&gt;&lt;/code&gt;&lt;br /&gt;&lt;br /&gt;I'm building MVC web applications where the controller classes resolve their dependencies in this way, and in order to test these controllers I have to provide the ServiceLocator with bindings to &lt;span style="font-style:italic;"&gt;mocks&lt;/span&gt;. But I'm probably getting ahead of myself just a little.&lt;br /&gt;&lt;br /&gt;Right... I realise I actually have to provide at least a little information on how Ninject works so that you, dear reader, have at least &lt;span style="font-style:italic;"&gt;some&lt;/span&gt; context. In order to facilitate dependency injection via Ninject, you create a &lt;span style="font-style:italic;"&gt;kernel&lt;/span&gt; and load this with one or more instances of &lt;span style="font-style:italic;"&gt;IModule&lt;/span&gt; which contain your bindings. Creation of the kernel might look something like&lt;br /&gt;&lt;br /&gt;&lt;code&gt;&lt;br /&gt;StandardKernel kernel = new StandardKernel(new MyBindingModule());&lt;br /&gt;&lt;/code&gt;&lt;br /&gt;&lt;br /&gt;where &lt;code&gt;MyBindingModule&lt;/code&gt; is a class that contains the bindings I require. Once again, for the sake of brevity I will not explain the intricate detail of how all this works, but for the sake of &lt;span style="font-style:italic;"&gt;continuity&lt;/span&gt; this is how MyBindingModule might look&lt;br /&gt;&lt;br /&gt;&lt;code&gt;&lt;br /&gt;public class MyBindingModule : StandardModule&lt;br /&gt;{&lt;br /&gt; public override void Load()&lt;br /&gt; {&lt;br /&gt;  Bind&amp;lt;ICategoryService&amp;gt;().To&amp;lt;CategoryService&amp;gt;();&lt;br /&gt; }&lt;br /&gt;}&lt;br /&gt;&lt;/code&gt;&lt;br /&gt;&lt;br /&gt;By creating a kernel and passing in &lt;code&gt;MyBindingModule&lt;/code&gt; to it, the kernel will know that whenever you request an instance of &lt;code&gt;ICategoryService&lt;/code&gt; it should create a new instance of the concrete class &lt;code&gt;CategoryService&lt;/code&gt; and return that back to you.&lt;br /&gt;&lt;br /&gt;Now, that's really great and really powerful stuff. You can set up loads of different bindings, even conditional bindings, and the kernel will happily resolve these for you and return you the right instance type whenever you need it. The only issue with this setup is that when it comes to unit testing, where you need to replace some of your standard bindings with mocks, this approach doesn't work.&lt;br /&gt;&lt;br /&gt;Why not? Because the kernel, by default, will resolve a binding and return a &lt;span style="font-style:italic;"&gt;new instance&lt;/span&gt; of the resolved type. If you're going to use mocks, this is no good because you need to have a handle on the actual mock instance so that you can set expectations and verify behaviours etc etc.&lt;br /&gt;&lt;br /&gt;Thankfully Ninject's got a nice little feature which allows you to bind a type to a &lt;span style="font-style:italic;"&gt;provider&lt;/span&gt;. The provider is a class (which you create) that's responsible for creating the object the kernel should return. Typically you'd use a provider when creation of an object is a complex task (e.g. it involves reading configuration files etc). We're not going to create a very complicated object, but we'll use a provider class so that we can ensure that the Ninject kernel resolves its bindings to specific mock instances that we've already created - rather than creating new instances that we have no access to.&lt;br /&gt;&lt;br /&gt;Before we go any further, let's just have a look at a simple test that injects a mock into another class. In this test we're going to create a mock for &lt;code&gt;ICategoryService&lt;/code&gt;, set an expectation on that mock, then inject the mock into a &lt;code&gt;CategoryController&lt;/code&gt; class (by means of its constructor), ask &lt;code&gt;CategoryController&lt;/code&gt; to do something for us, and lastly verify that the &lt;code&gt;CategoryController&lt;/code&gt; used the mock in the way we expected. Moq's my mocking framework of choice, but you could use any other framework if you like (Rhino Mocks, NMock, EasyMock, TypeMock etc).&lt;br /&gt;&lt;br /&gt;&lt;code&gt;&lt;br /&gt;[Test]&lt;br /&gt;public void TestAddingCategoryReturnsTrueFromService()&lt;br /&gt;{&lt;br /&gt; Category category = new Category(){ Id = 100};&lt;br /&gt; &lt;br /&gt; Mock&amp;lt;ICategoryService&amp;gt; serviceMock = new Mock&amp;lt;ICategoryService&amp;gt;();&lt;br /&gt; serviceMock.Expect(x =&amp;gt; x.Add(category)).Returns(true);&lt;br /&gt;&lt;br /&gt; CategoryController controller = new CategoryController(serviceMock.Object);&lt;br /&gt; controller.AddNewCategory(category);&lt;br /&gt;&lt;br /&gt; serviceMock.VerifyAll();&lt;br /&gt;}&lt;br /&gt;&lt;/code&gt;&lt;br /&gt;&lt;br /&gt;If you are at all familiar with mocking you'll the above test (created with NUnit) should present no mystery (other than it's a bit pointless, perhaps).&lt;br /&gt;&lt;br /&gt;We're going to change the scenario a bit, because we've no control over the creation of &lt;code&gt;CategoryController&lt;/code&gt; instances, so we can't inject dependencies via the constructor. Instead we'll let the &lt;code&gt;CategoryController&lt;/code&gt;'s default constructor make use of the ServiceLocator to resolve its dependencies:&lt;br /&gt;&lt;br /&gt;&lt;code&gt;&lt;br /&gt;public class CategoryController&lt;br /&gt;{&lt;br /&gt; private ICategoryService CategorySvc { get; set; }&lt;br /&gt;&lt;br /&gt; public CategoryController()&lt;br /&gt; {&lt;br /&gt;  CategorySvc = ServiceLocator.Instance.Get&amp;lt;ICategoryService&amp;gt;();&lt;br /&gt; }&lt;br /&gt;}&lt;br /&gt;&lt;/code&gt;&lt;br /&gt;&lt;br /&gt;Now we can no longer inject the mock directly into our the CategoryController. Instead we have to rely on Ninject to resolve the dependency for us. So now we'll load up the ServiceLocator with an IModule that has a binding to a &lt;span style="font-style:italic;"&gt;provider&lt;/span&gt; that we can prime with our mock. Hang on tight while we we have a look at our provider:&lt;br /&gt;&lt;br /&gt;&lt;code&gt;&lt;br /&gt;public class NInjectMockProvider&amp;lt;T&amp;gt; : SimpleProvider&amp;lt;T&amp;gt; where T : class&lt;br /&gt;{&lt;br /&gt;  public static Mock&amp;lt;T&amp;gt; Mock { get; set; }&lt;br /&gt;&lt;br /&gt;  protected override T CreateInstance(IContext context)&lt;br /&gt; {&lt;br /&gt;  if (Mock == null){ Mock = new Mock&amp;lt;T&amp;gt;(); }&lt;br /&gt;  return Mock.Object;&lt;br /&gt; }&lt;br /&gt;}&lt;br /&gt;&lt;/code&gt;&lt;br /&gt;&lt;br /&gt;It's straight forward, really. Our &lt;code&gt;NInjectMockProvider&amp;lt;T&amp;gt;&lt;/code&gt; extends &lt;code&gt;SimpleProvider&amp;lt;T&amp;gt;&lt;/code&gt;. The &lt;code&gt;CreateInstance(IContext context)&lt;/code&gt; method creates an instance of &lt;code&gt;Mock&amp;lt;T&amp;gt;&lt;/code&gt; and assigns this to the static property &lt;code&gt;Mock&lt;/code&gt;, unless this is &lt;span style="font-style:italic;"&gt;not null&lt;/span&gt;, and then returns the mocked object. Armed with this very simple provider and a new binding our test takes on a new shape alltogether. I've included the new test and binding below.&lt;br /&gt;&lt;br /&gt;&lt;code&gt;&lt;br /&gt;[Test]&lt;br /&gt;public void TestAddingCategoryReturnsTrueFromService()&lt;br /&gt;{&lt;br /&gt; //set up the ServiceLocator&lt;br /&gt; ServiceLocator locator = new ServiceLocator(new MyBindingModule());&lt;br /&gt;&lt;br /&gt; Category category = new Category() { Id = 100 };&lt;br /&gt; Mock&amp;lt;ICategoryService&amp;gt; serviceMock = new Mock&amp;lt;ICategoryService&amp;gt;();&lt;br /&gt; serviceMock.Expect(x =&amp;gt; x.Add(category)).Returns(true);&lt;br /&gt;&lt;br /&gt; NInjectMockProvider&amp;lt;ICategoryService&amp;gt;.Mock = serviceMock;&lt;br /&gt;&lt;br /&gt; //this is where the magic happens. The mock's been assigned to the provider, so&lt;br /&gt; //the controller will be automagically injected with the mock instance we&lt;br /&gt; //created above.&lt;br /&gt; CategoryController controller = new CategoryController();&lt;br /&gt;&lt;br /&gt; controller.AddNewCategory(category);&lt;br /&gt;&lt;br /&gt; serviceMock.VerifyAll();&lt;br /&gt;}&lt;br /&gt;&lt;br /&gt;public class MyBindingModule : StandardModule&lt;br /&gt;{&lt;br /&gt; public override void Load()&lt;br /&gt; {&lt;br /&gt;  Bind&amp;lt;ICategoryService&amp;gt;().ToProvider(new NInjectMockProvider&amp;lt;ICategoryService&amp;gt;());&lt;br /&gt; }&lt;br /&gt;}&lt;br /&gt;&lt;/code&gt;&lt;br /&gt;&lt;br /&gt;This example is specific to a scenario where we use the Service Locator pattern, but you can use the same approach and the same mock provider class in other situations as well where you'd like Ninject to resolve bindings to existing mock instances.&lt;br /&gt;&lt;br /&gt;I've found that the use of NinjectMockProvider&amp;lt;T&amp;gt; makes it easy to inject mocks and easy to read and understand the tests as well. Hopefully this can be of use to some of you out there.&lt;div class="blogger-post-footer"&gt;&lt;img width='1' height='1' src='https://blogger.googleusercontent.com/tracker/652174954000901332-7777887169958695703?l=www.babel-lutefisk.net'/&gt;&lt;/div&gt;&lt;img src="http://feeds.feedburner.com/~r/BabelLutefisk/~4/-QBlMOF6fkw" height="1" width="1"/&gt;</content><link rel="replies" type="application/atom+xml" href="http://www.babel-lutefisk.net/feeds/7777887169958695703/comments/default" title="Post Comments" /><link rel="replies" type="text/html" href="https://www.blogger.com/comment.g?blogID=652174954000901332&amp;postID=7777887169958695703" title="2 Comments" /><link rel="edit" type="application/atom+xml" href="http://www.blogger.com/feeds/652174954000901332/posts/default/7777887169958695703" /><link rel="self" type="application/atom+xml" href="http://www.blogger.com/feeds/652174954000901332/posts/default/7777887169958695703" /><link rel="alternate" type="text/html" href="http://feedproxy.google.com/~r/BabelLutefisk/~3/-QBlMOF6fkw/ninject-providers-and-moq-mock.html" title="Ninject providers and Moq mock injection." /><author><name>Øyvind Valland</name><uri>http://www.blogger.com/profile/17595718624373482981</uri><email>noreply@blogger.com</email><gd:extendedProperty xmlns:gd="http://schemas.google.com/g/2005" name="OpenSocialUserId" value="18377601055500046677" /></author><thr:total xmlns:thr="http://purl.org/syndication/thread/1.0">2</thr:total><feedburner:origLink>http://www.babel-lutefisk.net/2008/10/ninject-providers-and-moq-mock.html</feedburner:origLink></entry><entry><id>tag:blogger.com,1999:blog-652174954000901332.post-550866865448869003</id><published>2008-10-29T11:39:00.003Z</published><updated>2008-10-29T11:45:30.049Z</updated><category scheme="http://www.blogger.com/atom/ns#" term="Dependency Injection" /><category scheme="http://www.blogger.com/atom/ns#" term="Ninject" /><title type="text">Extension Method Issues with Ninject</title><content type="html">I thought I'd put this up here quickly as, hopefully, it may be of use to others who've come across and struggled with the extension method issue with &lt;a href="http://www.ninject.org"&gt;Ninject&lt;/a&gt;. I've got another post on Ninject and Moq mock injection coming up soon.&lt;br /&gt;&lt;br /&gt;If you've used Ninject in your .NET 3.5 projects you may have had occasional problems compiling your solution. If the compiler throws the &lt;span style="font-style:italic;"&gt;"Missing compiler required member 'System.Runtime.CompilerServices.ExtensionAttribute..ctor'"&lt;/span&gt; error, you've encountered an issue with the Ninject.Core.dll v1.0.0.82 which is currently available from &lt;a href="http://www.ninject.org"&gt;ninject.org&lt;/a&gt;.&lt;br /&gt;&lt;br /&gt;The issue is discussed &lt;a href="http://groups.google.com/group/ninject/browse_thread/thread/656ab431c67c7be5?pli=1"&gt;here&lt;/a&gt; but the solution to the problem isn't very clear. Though, if you read very carefully you'll find that you're encouraged to download the source and re-build Ninject yourself after adding a NET_35 pre-processor directive.&lt;br /&gt;&lt;br /&gt;As it turns out, &lt;a href="http://kohari.org/"&gt;Nate Kohari - father of Ninject -&lt;/a&gt; has fixed the issue and published the Ninject SVN trunk on the web. So all you need to do is point your SVN client (I use &lt;a href="http://tortoisesvn.tigris.org/"&gt;Tortoise&lt;/a&gt;) to &lt;a href="http://ninject.googlecode.com/svn/trunk/"&gt;http://ninject.googlecode.com/svn/trunk/&lt;/a&gt;, pull out the code, and build yourself a release version of the DLLs. &lt;br /&gt;&lt;br /&gt;Problem solved!&lt;div class="blogger-post-footer"&gt;&lt;img width='1' height='1' src='https://blogger.googleusercontent.com/tracker/652174954000901332-550866865448869003?l=www.babel-lutefisk.net'/&gt;&lt;/div&gt;&lt;img src="http://feeds.feedburner.com/~r/BabelLutefisk/~4/uO_pCk4tf_U" height="1" width="1"/&gt;</content><link rel="replies" type="application/atom+xml" href="http://www.babel-lutefisk.net/feeds/550866865448869003/comments/default" title="Post Comments" /><link rel="replies" type="text/html" href="https://www.blogger.com/comment.g?blogID=652174954000901332&amp;postID=550866865448869003" title="3 Comments" /><link rel="edit" type="application/atom+xml" href="http://www.blogger.com/feeds/652174954000901332/posts/default/550866865448869003" /><link rel="self" type="application/atom+xml" href="http://www.blogger.com/feeds/652174954000901332/posts/default/550866865448869003" /><link rel="alternate" type="text/html" href="http://feedproxy.google.com/~r/BabelLutefisk/~3/uO_pCk4tf_U/extension-method-issues-with-ninject.html" title="Extension Method Issues with Ninject" /><author><name>Øyvind Valland</name><uri>http://www.blogger.com/profile/17595718624373482981</uri><email>noreply@blogger.com</email><gd:extendedProperty xmlns:gd="http://schemas.google.com/g/2005" name="OpenSocialUserId" value="18377601055500046677" /></author><thr:total xmlns:thr="http://purl.org/syndication/thread/1.0">3</thr:total><feedburner:origLink>http://www.babel-lutefisk.net/2008/10/extension-method-issues-with-ninject.html</feedburner:origLink></entry><entry><id>tag:blogger.com,1999:blog-652174954000901332.post-8805073488157319781</id><published>2008-10-14T10:20:00.003+01:00</published><updated>2008-10-14T10:31:34.976+01:00</updated><category scheme="http://www.blogger.com/atom/ns#" term="MVC" /><category scheme="http://www.blogger.com/atom/ns#" term="Continuous Integration" /><title type="text">Problems with MVC and Continuous Integration</title><content type="html">It seems I don't have much time to write these days, but I've finally got another worthwhile piece to share. After sorting out our &lt;a href="http://www.babel-lutefisk.net/2008/09/fix-for-aspnet-mvc-preview-5-bug-with.html"&gt;issues with MVC Preview 5 on VS2008&lt;/a&gt;, we promptly ran into trouble when adding our MVC projects to the Continuous Integration process. The MVC project would not build because of missing DLL references. Steve had installed MVC Preview 5 on the build-server, so this was more than a little odd.&lt;br /&gt;&lt;br /&gt;However, after digging around for a while Steve found that this wasn't really an issue with missing DLLs on the build server at all. Rather, it was an issue with a couple of hintpaths in the MVC project file. The project file had stuff in it like this:&lt;br /&gt;&lt;br /&gt;&lt;a onblur="try {parent.deselectBloggerImageGracefully();} catch(e) {}" href="http://4.bp.blogspot.com/_uJz81f9t7xk/SPRmHsUvNPI/AAAAAAAAACg/GpGIAupqKYg/s1600-h/mvc_.bmp"&gt;&lt;img style="float:left; margin:0 10px 10px 0;cursor:pointer; cursor:hand;" src="http://4.bp.blogspot.com/_uJz81f9t7xk/SPRmHsUvNPI/AAAAAAAAACg/GpGIAupqKYg/s400/mvc_.bmp" border="0" alt=""id="BLOGGER_PHOTO_ID_5256938947391468786" /&gt;&lt;/a&gt;&lt;br /&gt;&lt;br /&gt;&lt;br /&gt;Do you see what's going on here? The hint-path is relative, and points to \Program Files\ on the C:\ drive! This is an issue for us, because the actual build happens on the E:\ drive of our build server. So... what to do?&lt;br /&gt;&lt;br /&gt;We use Subversion as our source repository, and frequently apply svn:externals to our project repos to pull in common third-party DLLs (such as Moq, NUnit, NInject etc). So why not use the same approach for the culprit MVC DLLs? That's exactly what we did and it solved the problem nicely.&lt;br /&gt;&lt;br /&gt;We've got a separate repository called BinaryDependencies which holds all our third-party DLLs. Whenever one or more of these DLLs are required we add a svn:external reference to the BinaryDependecies repository to pull in the relevant DLLs to the local project, and then it's simply a matter of replacing the existing references to Microsoft.Web.Mvc.dll (and any other offending reference that's broken) with a local reference. Simple!&lt;br /&gt;&lt;br /&gt;Of course, this isn't a lasting solution because you'll have to update the DLLs in the BinaryDependencies repository every time a new version of MVC comes out. BUT, it does get you up and runnig for now - and besides, MVC's soon going to be in Beta and first release... and I assume these particular problems will have been fixed by then!&lt;div class="blogger-post-footer"&gt;&lt;img width='1' height='1' src='https://blogger.googleusercontent.com/tracker/652174954000901332-8805073488157319781?l=www.babel-lutefisk.net'/&gt;&lt;/div&gt;&lt;img src="http://feeds.feedburner.com/~r/BabelLutefisk/~4/ETbKaU7q__U" height="1" width="1"/&gt;</content><link rel="replies" type="application/atom+xml" href="http://www.babel-lutefisk.net/feeds/8805073488157319781/comments/default" title="Post Comments" /><link rel="replies" type="text/html" href="https://www.blogger.com/comment.g?blogID=652174954000901332&amp;postID=8805073488157319781" title="3 Comments" /><link rel="edit" type="application/atom+xml" href="http://www.blogger.com/feeds/652174954000901332/posts/default/8805073488157319781" /><link rel="self" type="application/atom+xml" href="http://www.blogger.com/feeds/652174954000901332/posts/default/8805073488157319781" /><link rel="alternate" type="text/html" href="http://feedproxy.google.com/~r/BabelLutefisk/~3/ETbKaU7q__U/problems-with-mvc-and-continuous.html" title="Problems with MVC and Continuous Integration" /><author><name>Øyvind Valland</name><uri>http://www.blogger.com/profile/17595718624373482981</uri><email>noreply@blogger.com</email><gd:extendedProperty xmlns:gd="http://schemas.google.com/g/2005" name="OpenSocialUserId" value="18377601055500046677" /></author><media:thumbnail xmlns:media="http://search.yahoo.com/mrss/" url="http://4.bp.blogspot.com/_uJz81f9t7xk/SPRmHsUvNPI/AAAAAAAAACg/GpGIAupqKYg/s72-c/mvc_.bmp" height="72" width="72" /><thr:total xmlns:thr="http://purl.org/syndication/thread/1.0">3</thr:total><feedburner:origLink>http://www.babel-lutefisk.net/2008/10/problems-with-mvc-and-continuous.html</feedburner:origLink></entry><entry><id>tag:blogger.com,1999:blog-652174954000901332.post-7540717541571163979</id><published>2008-09-28T14:44:00.002+01:00</published><updated>2008-09-28T14:51:43.222+01:00</updated><title type="text">Significance</title><content type="html">From time to time I read or hear people talk about how unimportant we must be. In a universe so vast, on a planet so tiny, creatures like us must surely be insignificant indeed. And this, somehow, makes life pointless.&lt;br /&gt;&lt;br /&gt;I find it to be quite the contrary. In a universe so vast, so void of life, tiny creatures like us, living on such a tiny planet so far from anything else must certainly be &lt;span style="font-style:italic;"&gt;incredibly significant&lt;/span&gt;. Our existence would not make any sense otherwise.&lt;br /&gt;&lt;br /&gt;The point? When things &lt;span style="font-style:italic;"&gt;seem&lt;/span&gt; pointless, fundamentally they're anything but!&lt;div class="blogger-post-footer"&gt;&lt;img width='1' height='1' src='https://blogger.googleusercontent.com/tracker/652174954000901332-7540717541571163979?l=www.babel-lutefisk.net'/&gt;&lt;/div&gt;&lt;img src="http://feeds.feedburner.com/~r/BabelLutefisk/~4/ccAWqJcVSCU" height="1" width="1"/&gt;</content><link rel="replies" type="application/atom+xml" href="http://www.babel-lutefisk.net/feeds/7540717541571163979/comments/default" title="Post Comments" /><link rel="replies" type="text/html" href="https://www.blogger.com/comment.g?blogID=652174954000901332&amp;postID=7540717541571163979" title="0 Comments" /><link rel="edit" type="application/atom+xml" href="http://www.blogger.com/feeds/652174954000901332/posts/default/7540717541571163979" /><link rel="self" type="application/atom+xml" href="http://www.blogger.com/feeds/652174954000901332/posts/default/7540717541571163979" /><link rel="alternate" type="text/html" href="http://feedproxy.google.com/~r/BabelLutefisk/~3/ccAWqJcVSCU/significance.html" title="Significance" /><author><name>Øyvind Valland</name><uri>http://www.blogger.com/profile/17595718624373482981</uri><email>noreply@blogger.com</email><gd:extendedProperty xmlns:gd="http://schemas.google.com/g/2005" name="OpenSocialUserId" value="18377601055500046677" /></author><thr:total xmlns:thr="http://purl.org/syndication/thread/1.0">0</thr:total><feedburner:origLink>http://www.babel-lutefisk.net/2008/09/significance.html</feedburner:origLink></entry><entry><id>tag:blogger.com,1999:blog-652174954000901332.post-8662917128792011039</id><published>2008-09-24T12:09:00.004+01:00</published><updated>2008-09-26T09:47:50.197+01:00</updated><title type="text">Fix for ASP.NET MVC Preview 5 bug with Visual Studio 2008</title><content type="html">We've had some trouble using the latest &lt;a href="http://www.codeplex.com/aspnet/Release/ProjectReleases.aspx?ReleaseId=16775"&gt;ASP.NET MVC Preview 5&lt;/a&gt;. For reasons unknown any attempt to open a &lt;span style="font-style:italic;"&gt;view&lt;/span&gt; (e.g. Default.aspx, not the code-behind) in Visual Studio 2008 would cause a fatal .NET runtime error and the Visual Studio process would simply be killed. Dead. Gone.&lt;br /&gt;&lt;br /&gt;&lt;a onblur="try {parent.deselectBloggerImageGracefully();} catch(e) {}" href="http://4.bp.blogspot.com/_uJz81f9t7xk/SNoiY-RIJ2I/AAAAAAAAACY/YWfy1uiACqY/s1600-h/Fatal_Error_NETRuntime.bmp"&gt;&lt;img style="display:block; margin:0px auto 10px; text-align:center;cursor:pointer; cursor:hand;" src="http://4.bp.blogspot.com/_uJz81f9t7xk/SNoiY-RIJ2I/AAAAAAAAACY/YWfy1uiACqY/s400/Fatal_Error_NETRuntime.bmp" border="0" alt=""id="BLOGGER_PHOTO_ID_5249546128080775010" /&gt;&lt;/a&gt;&lt;br /&gt;&lt;br /&gt;Annoying.&lt;br /&gt;&lt;br /&gt;I spent a good amount of time trying to figure out why this could be, and though there were a few leads on the web none of the proposed solutions out there fixed the problem. So, I asked the senior developer on my team, Steve Friend, to have a look. Sic' em, Steve!&lt;br /&gt;&lt;br /&gt;Steve noticed that &lt;a href="http://weblogs.asp.net/scottgu/archive/2008/09/02/asp-net-mvc-preview-5-and-form-posting-scenarios.aspx"&gt;Scott Guthrie's Preview 5 Example Application&lt;/a&gt; wouldn't cause any problems at all. Nor would any MVC project added to the same solution as Guthrie's application. However, all other MVC projects created from scratch with Visual Studio would suffer from the symptom described at the top of this post.&lt;br /&gt;&lt;br /&gt;Steve examined the differences between ScottGu's application and a 'fresh' MVC app, and discovered that removing two of the DLLs from the fresh MVC app's /bin folder solved the problem. He documented this on our internal wiki, and I've copied-and-pasted his fix here. Thanks Steve!&lt;br /&gt;&lt;br /&gt;&lt;br /&gt;-------------&lt;br /&gt;&lt;span style="font-weight:bold;"&gt;Creating a new project&lt;/span&gt;&lt;br /&gt;In Visual Studio create a new MVC project (File &gt; New &gt; Project, then select Visual C# &gt; Web then select ASP.Net MVC Web Application). This will create a fairly large default project containing a number of folders and files relating to the MVC pattern structure (i.e. models, views and controllers).&lt;br /&gt;&lt;br /&gt;Once you have done this you will need to build the project and create a new website in IIS (see IISSetup for details of how to do this), but before you do that, run through the instructions below to avoid the bug that seems to ship with default projects.&lt;br /&gt;&lt;br /&gt;&lt;span style="font-weight:bold;"&gt;The bug&lt;/span&gt;&lt;br /&gt;If you double click on any view page (i.e. a aspx page) in order to edit it in Visual Studio the application crashes.&lt;br /&gt;&lt;br /&gt;&lt;span style="font-weight:bold;"&gt;The fix&lt;/span&gt;&lt;br /&gt;In the solution explorer select "Show all files" to reveal the bin folder. In there you will the following dlls (and possibly more, if you have already built your project/solution):&lt;br /&gt;&lt;br /&gt;    * Microsoft.Web.Mvc.dll&lt;br /&gt;    * System.Web.Abstractions.dll&lt;br /&gt;    * System.Web.Mvc.dll&lt;br /&gt;    * System.Web.Routing.dll &lt;br /&gt;&lt;br /&gt;Delete "System.Web.Abstractions.dll" and "System.Web.Routing.dll".&lt;div class="blogger-post-footer"&gt;&lt;img width='1' height='1' src='https://blogger.googleusercontent.com/tracker/652174954000901332-8662917128792011039?l=www.babel-lutefisk.net'/&gt;&lt;/div&gt;&lt;img src="http://feeds.feedburner.com/~r/BabelLutefisk/~4/qz46S7j_Ob8" height="1" width="1"/&gt;</content><link rel="replies" type="application/atom+xml" href="http://www.babel-lutefisk.net/feeds/8662917128792011039/comments/default" title="Post Comments" /><link rel="replies" type="text/html" href="https://www.blogger.com/comment.g?blogID=652174954000901332&amp;postID=8662917128792011039" title="5 Comments" /><link rel="edit" type="application/atom+xml" href="http://www.blogger.com/feeds/652174954000901332/posts/default/8662917128792011039" /><link rel="self" type="application/atom+xml" href="http://www.blogger.com/feeds/652174954000901332/posts/default/8662917128792011039" /><link rel="alternate" type="text/html" href="http://feedproxy.google.com/~r/BabelLutefisk/~3/qz46S7j_Ob8/fix-for-aspnet-mvc-preview-5-bug-with.html" title="Fix for ASP.NET MVC Preview 5 bug with Visual Studio 2008" /><author><name>Øyvind Valland</name><uri>http://www.blogger.com/profile/17595718624373482981</uri><email>noreply@blogger.com</email><gd:extendedProperty xmlns:gd="http://schemas.google.com/g/2005" name="OpenSocialUserId" value="18377601055500046677" /></author><media:thumbnail xmlns:media="http://search.yahoo.com/mrss/" url="http://4.bp.blogspot.com/_uJz81f9t7xk/SNoiY-RIJ2I/AAAAAAAAACY/YWfy1uiACqY/s72-c/Fatal_Error_NETRuntime.bmp" height="72" width="72" /><thr:total xmlns:thr="http://purl.org/syndication/thread/1.0">5</thr:total><feedburner:origLink>http://www.babel-lutefisk.net/2008/09/fix-for-aspnet-mvc-preview-5-bug-with.html</feedburner:origLink></entry><entry><id>tag:blogger.com,1999:blog-652174954000901332.post-4473241495678290152</id><published>2008-09-24T07:03:00.002+01:00</published><updated>2008-09-24T07:07:00.704+01:00</updated><title type="text">You know you're not a Digital Native when...</title><content type="html">... you get up in the morning, tune into Norwegian online radio (&lt;a href="http://nrkp3.no/"&gt;NRK P3&lt;/a&gt;, to be specific), and find yourself genuinely surprised  - when stepping out of the shower ten minutes later - that they're playing Norwegian rock band Dum Dum Boys. "But, but... we're in the UK?"&lt;br /&gt;&lt;br /&gt;Perhaps another few hours of chasing Zs is called for.&lt;div class="blogger-post-footer"&gt;&lt;img width='1' height='1' src='https://blogger.googleusercontent.com/tracker/652174954000901332-4473241495678290152?l=www.babel-lutefisk.net'/&gt;&lt;/div&gt;&lt;img src="http://feeds.feedburner.com/~r/BabelLutefisk/~4/DnPh3po6BQE" height="1" width="1"/&gt;</content><link rel="replies" type="application/atom+xml" href="http://www.babel-lutefisk.net/feeds/4473241495678290152/comments/default" title="Post Comments" /><link rel="replies" type="text/html" href="https://www.blogger.com/comment.g?blogID=652174954000901332&amp;postID=4473241495678290152" title="1 Comments" /><link rel="edit" type="application/atom+xml" href="http://www.blogger.com/feeds/652174954000901332/posts/default/4473241495678290152" /><link rel="self" type="application/atom+xml" href="http://www.blogger.com/feeds/652174954000901332/posts/default/4473241495678290152" /><link rel="alternate" type="text/html" href="http://feedproxy.google.com/~r/BabelLutefisk/~3/DnPh3po6BQE/you-know-youre-not-digital-native-when.html" title="You know you're not a Digital Native when..." /><author><name>Øyvind Valland</name><uri>http://www.blogger.com/profile/17595718624373482981</uri><email>noreply@blogger.com</email><gd:extendedProperty xmlns:gd="http://schemas.google.com/g/2005" name="OpenSocialUserId" value="18377601055500046677" /></author><thr:total xmlns:thr="http://purl.org/syndication/thread/1.0">1</thr:total><feedburner:origLink>http://www.babel-lutefisk.net/2008/09/you-know-youre-not-digital-native-when.html</feedburner:origLink></entry><entry><id>tag:blogger.com,1999:blog-652174954000901332.post-7180254045471351031</id><published>2008-08-25T12:07:00.002+01:00</published><updated>2008-08-25T12:16:12.505+01:00</updated><category scheme="http://www.blogger.com/atom/ns#" term="Database" /><category scheme="http://www.blogger.com/atom/ns#" term="Visual Studio" /><category scheme="http://www.blogger.com/atom/ns#" term="Continuous Integration" /><title type="text">Building your DBs with VS 2008 Database Edition</title><content type="html">This is going to be a quick one, but I feel the database projects in VS 2008 Database Edition are worth a mention.&lt;br /&gt;&lt;br /&gt;I've just set up the first database project for my client using VS 2008. The Database Edition of VS 2008 is an improvement on the database project extensions for VS 2005, and makes database development, maintenance, and deployment really simple.&lt;br /&gt;&lt;br /&gt;The database project puts the &lt;span style="font-style:italic;"&gt;entire&lt;/span&gt; DB schema into a structured format (either by schema or object type). You can easily add, modify, or delete tables, sprocs, constraints, functions, etc - and running comparisons of a DB project and a database instance (or between two DBs or two DB projects) is a breeze.&lt;br /&gt;&lt;br /&gt;The DB project can be &lt;span style="font-style:italic;"&gt;built&lt;/span&gt;, which means you've got full DB integrity checks at the click of a button. Even better, you can add the entire solution to your source control repository of choice, and include it in your continuous integration cycle. I set this up with SVN and CCNET, and now every single change to the DB is verified upon build.&lt;br /&gt;&lt;br /&gt;How did we manage before?&lt;div class="blogger-post-footer"&gt;&lt;img width='1' height='1' src='https://blogger.googleusercontent.com/tracker/652174954000901332-7180254045471351031?l=www.babel-lutefisk.net'/&gt;&lt;/div&gt;&lt;img src="http://feeds.feedburner.com/~r/BabelLutefisk/~4/jOZFQogLW2s" height="1" width="1"/&gt;</content><link rel="replies" type="application/atom+xml" href="http://www.babel-lutefisk.net/feeds/7180254045471351031/comments/default" title="Post Comments" /><link rel="replies" type="text/html" href="https://www.blogger.com/comment.g?blogID=652174954000901332&amp;postID=7180254045471351031" title="0 Comments" /><link rel="edit" type="application/atom+xml" href="http://www.blogger.com/feeds/652174954000901332/posts/default/7180254045471351031" /><link rel="self" type="application/atom+xml" href="http://www.blogger.com/feeds/652174954000901332/posts/default/7180254045471351031" /><link rel="alternate" type="text/html" href="http://feedproxy.google.com/~r/BabelLutefisk/~3/jOZFQogLW2s/building-your-dbs-with-vs-2008-database.html" title="Building your DBs with VS 2008 Database Edition" /><author><name>Øyvind Valland</name><uri>http://www.blogger.com/profile/17595718624373482981</uri><email>noreply@blogger.com</email><gd:extendedProperty xmlns:gd="http://schemas.google.com/g/2005" name="OpenSocialUserId" value="18377601055500046677" /></author><thr:total xmlns:thr="http://purl.org/syndication/thread/1.0">0</thr:total><feedburner:origLink>http://www.babel-lutefisk.net/2008/08/building-your-dbs-with-vs-2008-database.html</feedburner:origLink></entry><entry><id>tag:blogger.com,1999:blog-652174954000901332.post-4666478309257719519</id><published>2008-07-24T17:21:00.002+01:00</published><updated>2008-07-24T17:28:01.127+01:00</updated><category scheme="http://www.blogger.com/atom/ns#" term="Visual Studio" /><title type="text">DB access problems with VS 2008 Database Edition</title><content type="html">I've just installed VS 2008 Database Edition to help with managing the new databases for my current project. The DB project templates in VS 2008 DE provide a really clean way of managing all the DB objects and makes it easy to have it all under source control as well.&lt;br /&gt;&lt;br /&gt;However I ran into trouble setting up the projects and kept getting the following error: &lt;span style="font-style:italic;"&gt;An error has occurred while establishing a connection to the server.  When connecting to SQL Server 2005, this failure may be caused by the fact that under the default settings SQL Server does not allow remote connections. (provider: SQL Network Interfaces, error: 26 - Error Locating Server/Instance Specified)&lt;/span&gt;.&lt;br /&gt;&lt;br /&gt;In typical Microsoft style there's no help attached to that error; Sorry Mac, you're on your own.&lt;br /&gt;&lt;br /&gt;A bit of digging around revealed two things: You &lt;span style="font-style:italic;"&gt;must&lt;/span&gt; specify a target database for your project (if you don't it'll try and connect to the default instance on your machine and that won't work) and you have to enable the SQL Server Express service on your machine as this DB is used by the project for storing comparison data etc.&lt;br /&gt;&lt;br /&gt;Most women will claim that men are reluctant to stop for directions and to read the instructions for the gadget they just bought. Maybe so. I didn't bother reading the tutorials on setting up the project. But blimey, it could certainly be made more intuitive!&lt;br /&gt;&lt;br /&gt;Anyway, this post is more of a Note To Self - but if it helps you, too, then great!&lt;div class="blogger-post-footer"&gt;&lt;img width='1' height='1' src='https://blogger.googleusercontent.com/tracker/652174954000901332-4666478309257719519?l=www.babel-lutefisk.net'/&gt;&lt;/div&gt;&lt;img src="http://feeds.feedburner.com/~r/BabelLutefisk/~4/FO-5Uyztfpw" height="1" width="1"/&gt;</content><link rel="replies" type="application/atom+xml" href="http://www.babel-lutefisk.net/feeds/4666478309257719519/comments/default" title="Post Comments" /><link rel="replies" type="text/html" href="https://www.blogger.com/comment.g?blogID=652174954000901332&amp;postID=4666478309257719519" title="0 Comments" /><link rel="edit" type="application/atom+xml" href="http://www.blogger.com/feeds/652174954000901332/posts/default/4666478309257719519" /><link rel="self" type="application/atom+xml" href="http://www.blogger.com/feeds/652174954000901332/posts/default/4666478309257719519" /><link rel="alternate" type="text/html" href="http://feedproxy.google.com/~r/BabelLutefisk/~3/FO-5Uyztfpw/db-access-problems-with-vs-2008.html" title="DB access problems with VS 2008 Database Edition" /><author><name>Øyvind Valland</name><uri>http://www.blogger.com/profile/17595718624373482981</uri><email>noreply@blogger.com</email><gd:extendedProperty xmlns:gd="http://schemas.google.com/g/2005" name="OpenSocialUserId" value="18377601055500046677" /></author><thr:total xmlns:thr="http://purl.org/syndication/thread/1.0">0</thr:total><feedburner:origLink>http://www.babel-lutefisk.net/2008/07/db-access-problems-with-vs-2008.html</feedburner:origLink></entry><entry><id>tag:blogger.com,1999:blog-652174954000901332.post-8614976567185847182</id><published>2008-07-19T18:28:00.004+01:00</published><updated>2008-07-19T18:53:15.397+01:00</updated><category scheme="http://www.blogger.com/atom/ns#" term=".NET" /><category scheme="http://www.blogger.com/atom/ns#" term="C#" /><title type="text">Automatic properties; a great idea?</title><content type="html">A little while ago I had a conversation with another guy about coding standards and the subject of member variable prefixing came up. I'm a real fan of underscore prefixes like &lt;code&gt;private string _firstName;&lt;/code&gt; and suggested that this be included in the coding standard so as to avoid problems stemming from sloppy coding and member names varying by case only.&lt;br /&gt;&lt;br /&gt;I've come across many a class where the coder intended to access the property &lt;code&gt;FirstName&lt;/code&gt; but - possibly because of IntelliSense or other code-completion shenanigans - ended up accessing the member variable &lt;code&gt;firstName&lt;/code&gt; instead. If member variables are consistently prefixed then this isn't a problem. I like the underscore because it stands out, it's just one character, and it kind of &lt;span style="font-style:italic;"&gt;anchors&lt;/span&gt; the variable to the class or scope.&lt;br /&gt;&lt;br /&gt;Anyway, the chap I was speaking to said "sure, we can use prefixes but it really isn't so necessary because we'll just use automatic properties instead."&lt;br /&gt;&lt;br /&gt;Hmmmm..... Simpson, hey?&lt;br /&gt;&lt;br /&gt;Today in C# you've the ability to declare typed properties which hide the underlying variable. In other words, there's no longer the need to declare a private member variable and expose it explicitly through a public property. Now all you have to do is create the property itself, like this:&lt;br /&gt;&lt;code&gt;&lt;br /&gt;public class Person&lt;br /&gt;{&lt;br /&gt;  public string FirstName { get; set; }&lt;br /&gt;  public string LastName { get; set; }&lt;br /&gt;}&lt;br /&gt;&lt;/code&gt;&lt;br /&gt;It &lt;span style="font-style:italic;"&gt;is&lt;/span&gt; a pretty cool feature. But it's really limited as well. If you want to do anything but expose a variable on your class' interface, you can't use automatic properties. You can define the setter as &lt;code&gt;private&lt;/code&gt; but that's about the flexibility you have. &lt;br /&gt;&lt;br /&gt;Once you start to tamper with either the getter or setter your property is no longer considered automatic, so you're back to good old normal properties. It seems to me there's not a whole lot to be gained from automatic properties because in my experience and, more often than not, you typically want to do something other than access a member variable (at least in the setter) when the property is called.&lt;br /&gt;&lt;br /&gt;Oh, and another thing: Automatic properties aren't debuggable. You can set a breakpoint on an automatic property but it will never be hit. Boo.&lt;br /&gt;&lt;br /&gt;I reckon that in the future we'll be able to have another kind of automatic property where you actually &lt;span style="font-style:italic;"&gt;can&lt;/span&gt; access the get/set variable, validate, or do whatever you like. &lt;br /&gt;&lt;br /&gt;For now the automatic property is nothing but a bit of syntactic sugar. I'm on a diet (ha-ha!) so I'm likely to stay clear.&lt;div class="blogger-post-footer"&gt;&lt;img width='1' height='1' src='https://blogger.googleusercontent.com/tracker/652174954000901332-8614976567185847182?l=www.babel-lutefisk.net'/&gt;&lt;/div&gt;&lt;img src="http://feeds.feedburner.com/~r/BabelLutefisk/~4/E2I6_fsT2Yc" height="1" width="1"/&gt;</content><link rel="replies" type="application/atom+xml" href="http://www.babel-lutefisk.net/feeds/8614976567185847182/comments/default" title="Post Comments" /><link rel="replies" type="text/html" href="https://www.blogger.com/comment.g?blogID=652174954000901332&amp;postID=8614976567185847182" title="2 Comments" /><link rel="edit" type="application/atom+xml" href="http://www.blogger.com/feeds/652174954000901332/posts/default/8614976567185847182" /><link rel="self" type="application/atom+xml" href="http://www.blogger.com/feeds/652174954000901332/posts/default/8614976567185847182" /><link rel="alternate" type="text/html" href="http://feedproxy.google.com/~r/BabelLutefisk/~3/E2I6_fsT2Yc/automatic-properties-great-idea.html" title="Automatic properties; a great idea?" /><author><name>Øyvind Valland</name><uri>http://www.blogger.com/profile/17595718624373482981</uri><email>noreply@blogger.com</email><gd:extendedProperty xmlns:gd="http://schemas.google.com/g/2005" name="OpenSocialUserId" value="18377601055500046677" /></author><thr:total xmlns:thr="http://purl.org/syndication/thread/1.0">2</thr:total><feedburner:origLink>http://www.babel-lutefisk.net/2008/07/automatic-properties-great-idea.html</feedburner:origLink></entry><entry><id>tag:blogger.com,1999:blog-652174954000901332.post-2155738584054604396</id><published>2008-07-18T14:11:00.006+01:00</published><updated>2008-07-18T14:22:49.634+01:00</updated><title type="text">Exploitative software</title><content type="html">At the Rotterdam Central metro station last weekend they were having some trouble with their ticketing machines. Have a close look at the OS names.&lt;br /&gt;&lt;br /&gt;Seems they've one for your every day tickets (the purely fabricated prices) and one for special occasions... like festival weekends for example. Fire up the Exploitation OS, sonny!&lt;br /&gt;&lt;br /&gt;&lt;a onblur="try {parent.deselectBloggerImageGracefully();} catch(e) {}" href="http://bp3.blogger.com/_uJz81f9t7xk/SICXHwMeMOI/AAAAAAAAABE/ZSNiwW_A8mw/s1600-h/DSC00280.JPG"&gt;&lt;img style="float:left; margin:0px auto 10px; padding:10px; text-align:center;cursor:pointer; cursor:hand;" src="http://bp3.blogger.com/_uJz81f9t7xk/SICXHwMeMOI/AAAAAAAAABE/ZSNiwW_A8mw/s400/DSC00280.JPG" border="0" alt=""id="BLOGGER_PHOTO_ID_5224341727201865954" /&gt;&lt;/a&gt;&lt;a onblur="try {parent.deselectBloggerImageGracefully();} catch(e) {}" href="http://bp2.blogger.com/_uJz81f9t7xk/SICXIJjAOHI/AAAAAAAAABM/xnZTgix5HD4/s1600-h/DSC00281.JPG"&gt;&lt;img style="float:left; margin:0px auto 10px; padding:10px; text-align:center;cursor:pointer; cursor:hand;" src="http://bp2.blogger.com/_uJz81f9t7xk/SICXIJjAOHI/AAAAAAAAABM/xnZTgix5HD4/s400/DSC00281.JPG" border="0" alt=""id="BLOGGER_PHOTO_ID_5224341734007257202" /&gt;&lt;/a&gt;&lt;div class="blogger-post-footer"&gt;&lt;img width='1' height='1' src='https://blogger.googleusercontent.com/tracker/652174954000901332-2155738584054604396?l=www.babel-lutefisk.net'/&gt;&lt;/div&gt;&lt;img src="http://feeds.feedburner.com/~r/BabelLutefisk/~4/CXquFZvYqYk" height="1" width="1"/&gt;</content><link rel="replies" type="application/atom+xml" href="http://www.babel-lutefisk.net/feeds/2155738584054604396/comments/default" title="Post Comments" /><link rel="replies" type="text/html" href="https://www.blogger.com/comment.g?blogID=652174954000901332&amp;postID=2155738584054604396" title="0 Comments" /><link rel="edit" type="application/atom+xml" href="http://www.blogger.com/feeds/652174954000901332/posts/default/2155738584054604396" /><link rel="self" type="application/atom+xml" href="http://www.blogger.com/feeds/652174954000901332/posts/default/2155738584054604396" /><link rel="alternate" type="text/html" href="http://feedproxy.google.com/~r/BabelLutefisk/~3/CXquFZvYqYk/exploitative-software.html" title="Exploitative software" /><author><name>Øyvind Valland</name><uri>http://www.blogger.com/profile/17595718624373482981</uri><email>noreply@blogger.com</email><gd:extendedProperty xmlns:gd="http://schemas.google.com/g/2005" name="OpenSocialUserId" value="18377601055500046677" /></author><media:thumbnail xmlns:media="http://search.yahoo.com/mrss/" url="http://bp3.blogger.com/_uJz81f9t7xk/SICXHwMeMOI/AAAAAAAAABE/ZSNiwW_A8mw/s72-c/DSC00280.JPG" height="72" width="72" /><thr:total xmlns:thr="http://purl.org/syndication/thread/1.0">0</thr:total><feedburner:origLink>http://www.babel-lutefisk.net/2008/07/exploitative-software.html</feedburner:origLink></entry><entry><id>tag:blogger.com,1999:blog-652174954000901332.post-7087867224652791476</id><published>2008-07-17T23:29:00.007+01:00</published><updated>2008-07-17T23:37:35.542+01:00</updated><title type="text">Go Wordle yourself</title><content type="html">&lt;a onblur="try {parent.deselectBloggerImageGracefully();} catch(e) {}" href="http://bp0.blogger.com/_uJz81f9t7xk/SH_JIypoCXI/AAAAAAAAAA8/Cqbzr51Ffuw/s1600-h/wordle.JPG"&gt;&lt;img style="float:right; margin:0 10px 10px 0;cursor:pointer; cursor:hand;" src="http://bp0.blogger.com/_uJz81f9t7xk/SH_JIypoCXI/AAAAAAAAAA8/Cqbzr51Ffuw/s400/wordle.JPG" border="0" alt=""id="BLOGGER_PHOTO_ID_5224115245645564274" /&gt;&lt;/a&gt;&lt;br /&gt;I just had to try this. Very cool idea. Check out &lt;a href="http://wordle.net/"&gt;Wordle&lt;/a&gt; and get your own graphical representation of the stuff that comes out of your head and onto the page. Judging by this picture my blog certainly does not look very technical. Why "Address" is so prominent I've no idea. But I like the idea, and it looks kind of cool, no?&lt;div class="blogger-post-footer"&gt;&lt;img width='1' height='1' src='https://blogger.googleusercontent.com/tracker/652174954000901332-7087867224652791476?l=www.babel-lutefisk.net'/&gt;&lt;/div&gt;&lt;img src="http://feeds.feedburner.com/~r/BabelLutefisk/~4/GjZOlAxr0-s" height="1" width="1"/&gt;</content><link rel="replies" type="application/atom+xml" href="http://www.babel-lutefisk.net/feeds/7087867224652791476/comments/default" title="Post Comments" /><link rel="replies" type="text/html" href="https://www.blogger.com/comment.g?blogID=652174954000901332&amp;postID=7087867224652791476" title="0 Comments" /><link rel="edit" type="application/atom+xml" href="http://www.blogger.com/feeds/652174954000901332/posts/default/7087867224652791476" /><link rel="self" type="application/atom+xml" href="http://www.blogger.com/feeds/652174954000901332/posts/default/7087867224652791476" /><link rel="alternate" type="text/html" href="http://feedproxy.google.com/~r/BabelLutefisk/~3/GjZOlAxr0-s/go-wordle-yourself.html" title="Go Wordle yourself" /><author><name>Øyvind Valland</name><uri>http://www.blogger.com/profile/17595718624373482981</uri><email>noreply@blogger.com</email><gd:extendedProperty xmlns:gd="http://schemas.google.com/g/2005" name="OpenSocialUserId" value="18377601055500046677" /></author><media:thumbnail xmlns:media="http://search.yahoo.com/mrss/" url="http://bp0.blogger.com/_uJz81f9t7xk/SH_JIypoCXI/AAAAAAAAAA8/Cqbzr51Ffuw/s72-c/wordle.JPG" height="72" width="72" /><thr:total xmlns:thr="http://purl.org/syndication/thread/1.0">0</thr:total><feedburner:origLink>http://www.babel-lutefisk.net/2008/07/go-wordle-yourself.html</feedburner:origLink></entry><entry><id>tag:blogger.com,1999:blog-652174954000901332.post-8228412314021596827</id><published>2008-07-17T22:57:00.004+01:00</published><updated>2008-07-17T23:21:03.474+01:00</updated><category scheme="http://www.blogger.com/atom/ns#" term="Agility" /><title type="text">I just can't shut up about it</title><content type="html">&lt;a onblur="try {parent.deselectBloggerImageGracefully();} catch(e) {}" href="http://bp2.blogger.com/_uJz81f9t7xk/SH_BH1pKCxI/AAAAAAAAAAk/XTltzQPp41E/s1600-h/shut.jpg"&gt;&lt;img style="float:left; margin:0 10px 10px 0;cursor:pointer; cursor:hand;" src="http://bp2.blogger.com/_uJz81f9t7xk/SH_BH1pKCxI/AAAAAAAAAAk/XTltzQPp41E/s320/shut.jpg" border="0" alt=""id="BLOGGER_PHOTO_ID_5224106433176013586" /&gt;&lt;/a&gt;&lt;br /&gt;Agile. I use that word so many times a day now I'm starting to sound like a salesperson. Not good. But I'm deliberately keeping my vocabulary small (keeping it &lt;span style="font-style:italic;"&gt;simple&lt;/span&gt;) so that at least what people hear is consistent.&lt;br /&gt;&lt;br /&gt;I have been interviewing business analysts lately and it's important to me - surprise, surprise - that they have experience with both analysis and project management in an agile environment. As it turns out, the guys that I've liked have a similar idea to mine about agile methodology: One should be agile about that, too!&lt;br /&gt;&lt;br /&gt;What I mean by this is that if you're truly agile you don't lock yourself into one single methodology for running your project. It's better to mix and match, pick and choose, chop and change. Construct your own methodology from a set of others and make it fit your situation, your constraints, your experience.&lt;br /&gt;&lt;br /&gt;Why is this important? Because the less you impose process, the more nimble you are.&lt;br /&gt;&lt;br /&gt;I've had some interesting discussions around this recently. I'm leading a new project, a new and exciting build. It's the ever elusive greenfield. A chance to do something new, something different, to try different shoes on and throw away those that don't fit. This is why I accepted the challenge, because of all these opportunities. And I have been adamant that we should be nimble, flexible, agile all along, and that we should use this opportunity for all that it's worth to try new things.&lt;br /&gt;&lt;br /&gt;But my ideas were almost stopped dead because the company that I'm working for currently has a massive IT initiative underway to put in place required processes to manage their rapidly growing development team (which is up by 300% in a matter of months) while at the same time refactoring and rebuilding an aging and highly coupled trading platform. &lt;br /&gt;&lt;br /&gt;The team undertaking this work is already so big and now growing so fast that they &lt;span style="font-style:italic;"&gt;need&lt;/span&gt; process. I argued that the team that I'll be leading is so small that we really don't need all that process. I argued long and hard and had to turn to many different people before I could finally convince the IT leadership that it really is OK to go light on process and tools and support systems when you're in the early phases of something like this.&lt;br /&gt;&lt;br /&gt;There is no need for a full blown Team Foundation System setup with all its bells and whistles. Subversion does the trick, and it does it beautifully. There's no need for meetings about every aspect of what we are about to embark on. There's no need to define processes for this, that, and everything in-between. In my case, we're kicking off a proof-of-concept project that later will - hopefully&lt;span style="font-style:italic;"&gt;!&lt;/span&gt; - end up becoming a large scale development with full IT and business backing. Right now, we just need to get on with our POC with minimal hassle and minimal interference. Later on, when the business says "Yes this is great! Here, have a wad of cash", &lt;span style="font-style:italic;"&gt;that's&lt;/span&gt; when we should start looking at any extra processes and tools and systems we might need to put in place.&lt;br /&gt;&lt;br /&gt;I've spoken before about things being a problem only when they are a problem. Anticipating a need for process months prematurely just creates a problem from a notion of something that doesn't exist. Remember that. YAGNI applies not just in best-practice coding guides, it applies to &lt;span style="font-style:italic;"&gt;everything&lt;/span&gt; that can be labeled as agile.&lt;br /&gt;&lt;br /&gt;So, in final words and a note-to-self: Shut up and do it!&lt;div class="blogger-post-footer"&gt;&lt;img width='1' height='1' src='https://blogger.googleusercontent.com/tracker/652174954000901332-8228412314021596827?l=www.babel-lutefisk.net'/&gt;&lt;/div&gt;&lt;img src="http://feeds.feedburner.com/~r/BabelLutefisk/~4/vcVBmVG_eF4" height="1" width="1"/&gt;</content><link rel="replies" type="application/atom+xml" href="http://www.babel-lutefisk.net/feeds/8228412314021596827/comments/default" title="Post Comments" /><link rel="replies" type="text/html" href="https://www.blogger.com/comment.g?blogID=652174954000901332&amp;postID=8228412314021596827" title="0 Comments" /><link rel="edit" type="application/atom+xml" href="http://www.blogger.com/feeds/652174954000901332/posts/default/8228412314021596827" /><link rel="self" type="application/atom+xml" href="http://www.blogger.com/feeds/652174954000901332/posts/default/8228412314021596827" /><link rel="alternate" type="text/html" href="http://feedproxy.google.com/~r/BabelLutefisk/~3/vcVBmVG_eF4/i-just-cant-shut-up-about-it.html" title="I just can't shut up about it" /><author><name>Øyvind Valland</name><uri>http://www.blogger.com/profile/17595718624373482981</uri><email>noreply@blogger.com</email><gd:extendedProperty xmlns:gd="http://schemas.google.com/g/2005" name="OpenSocialUserId" value="18377601055500046677" /></author><media:thumbnail xmlns:media="http://search.yahoo.com/mrss/" url="http://bp2.blogger.com/_uJz81f9t7xk/SH_BH1pKCxI/AAAAAAAAAAk/XTltzQPp41E/s72-c/shut.jpg" height="72" width="72" /><thr:total xmlns:thr="http://purl.org/syndication/thread/1.0">0</thr:total><feedburner:origLink>http://www.babel-lutefisk.net/2008/07/i-just-cant-shut-up-about-it.html</feedburner:origLink></entry><entry><id>tag:blogger.com,1999:blog-652174954000901332.post-7222927740202947410</id><published>2008-07-08T23:21:00.005+01:00</published><updated>2008-07-09T08:44:24.258+01:00</updated><category scheme="http://www.blogger.com/atom/ns#" term="Getting Real" /><category scheme="http://www.blogger.com/atom/ns#" term="Quality" /><category scheme="http://www.blogger.com/atom/ns#" term="Agility" /><title type="text">More and more about agility</title><content type="html">I'm on a bit of a roll with agile thinking at the moment. As you can surmise from a &lt;a href="http://www.babel-lutefisk.net/2008/07/few-more-words-on-agility.html"&gt;previous post&lt;/a&gt;, the thinking in my current environment has traditionally been anything but agile.&lt;br /&gt;&lt;br /&gt;It's not uncommon. While agile is a buzzword and everybody's talking about it, there are still a lot of people to whom the concept is still vague, unfamiliar, strange, alien - just not something they understand. It's been the case here, and it's now slowly changing.&lt;br /&gt;&lt;br /&gt;I've talked about M before. M's smart. He's sharp. He gets things. You show him an article on a concept he's never heard about before and he'll grasp it within an amazingly short amount of time. This happened when I showed him the &lt;a href="http://gettingreal.37signals.com/"&gt;Getting Real&lt;/a&gt; book by 37Signals. He got it.&lt;br /&gt;&lt;br /&gt;Though, he doesn't always get it entirely. And I am not one to blame him in this case. Moving on from your typical waterfall, specify-in-entirety-then-develop-till-it's-done approach to a an approach that says "let's just do what's right for right now and then see what's next" would demand a lot from most of us. So in M's case going agile so far means going from one iteration to three iterations.&lt;br /&gt;&lt;br /&gt;That's a far cry from being agile because if you're truly developing in an agile manner you have no idea how many iterations you'll need. More likely, you'll have an infinite number of iterations.&lt;br /&gt;&lt;br /&gt;At first M's initial take on agile frustrated me, but then I thought about it and now it doesn't bother me at all. Why? Because of something that I read in 37Signals' book. It says&lt;blockquote&gt;It's a Problem When It's a Problem&lt;/blockquote&gt;In other words, if you think something is going to be a problem, don't worry about it until it actually becomes a problem. M's three-iterations-is-agile isn't a problem because he doesn't know what the first iteration is yet. Even more to the point, when we've all agreed on what the first iteration entails, he'll see (as the iteration nears it's end) that iteration number two looks a whole lot different than what he thought before we started.&lt;br /&gt;&lt;br /&gt;As a friend put it the other night, it's kind of like going through cycles of throwing away requirements. What you thought was a requirement a month ago suddenly no longer applies or has been replaced by three other requirements - all because your small iterations bring you a workable representation of software that is &lt;span style="font-style:italic;"&gt;real and tangible&lt;/span&gt;. Real and tangible things give you &lt;span style="font-style:italic;"&gt;experiences&lt;/span&gt;. &lt;span style="font-style:italic;"&gt;Experiences&lt;/span&gt; can give you ideas about how to make that particular experience even better. &lt;br /&gt;&lt;br /&gt;And that's as simple as it is. Small-step enhancements. A few of those, based on experience, give you a whole lot more than one big effort based on assumption.&lt;br /&gt;&lt;br /&gt;I should give a couple of examples here on what this means, in real terms.&lt;br /&gt;&lt;br /&gt;At my previous employer we had a kind of semi-agile approach to developing software. For the greater part it was good, but sometimes we'd get these over-specified documents that told us not only what the customer wanted but also exactly how it should be done (read: implemented).&lt;br /&gt;&lt;br /&gt;Pardon me, but if you're hiring me to build software for you, you're leaving the "how" more or less up to me. Anyway...&lt;br /&gt;&lt;br /&gt;So I got this requirements document for a customer management tool. And it had this section in it about the "Address Book" and how it should look and work. Every address should be displayed in a certain way, and if an address was a customer's designated billing or shipping address they should appear at the top of the listing (with the billing address appearing first) and be clearly marked as either "Billing" or "Shipping". And the Address Book should paginate all addresses. And to make a n address a billing address there should be a button to click next to the address listing. And the same applies to making an address a shipping address. These were, more or less, the requirements.&lt;br /&gt;&lt;br /&gt;We (the team of developers) had a chat about it. And we dropped the pagination, because we figured not many customers would have enough addresses to really need pagination. And we dropped the "click-button-to-make-special" idea.&lt;br /&gt;&lt;br /&gt;Instead we just listed the addresses on a page and put two columns next to them with checkboxes in them, one to indicate that an address is a shipping address and one to indicate that the address is a billing address.&lt;br /&gt;&lt;br /&gt;No pagination, no buttons, no automatic re-ordering of the way addresses are listed. Instead we did it nice, clean, and simple.&lt;br /&gt;&lt;br /&gt;Guess what? It worked just fine. And when the time comes that enough customers complain that it's &lt;span style="font-style:italic;"&gt;not&lt;/span&gt; working just fine for one reason or another... well, then I bet they'll change it.&lt;br /&gt;&lt;br /&gt;Another example:  A different part of that same application required that we could display and validate data according to a client's specific demands. We had one running instance of the application so we did this by extending standard ASP.NET controls as &lt;span style="font-style:italic;"&gt;user&lt;/span&gt; controls and building a simple templating system around it. It took one of our developers just under a week to do this. It worked. It was nice and simple. But there was one potential drawback...&lt;br /&gt;&lt;br /&gt;Because we'd developed this templating solution using &lt;span style="font-style:italic;"&gt;user controls&lt;/span&gt; we couldn't re-use it in other applications. We thought we might need to re-use this functionality elsewhere, so we talked about re-building it all using &lt;span style="font-style:italic;"&gt;server controls&lt;/span&gt; and custom configuration blocks etc etc etc. But in the end we didn't. Because we didn't need it &lt;span style="font-style:italic;"&gt;then&lt;/span&gt;.&lt;br /&gt;&lt;br /&gt;As far as I know they haven't needed it since, either. But the day may come when they do need it, and then they'll build it.&lt;br /&gt;&lt;br /&gt;These are some key examples on what it &lt;span style="font-style:italic;"&gt;actually means to be agile&lt;/span&gt;. It's not about being lazy, it's about being smart.&lt;br /&gt;&lt;br /&gt;&lt;br /&gt;... and now that this is out of my system it's time to hit the sack :-)&lt;div class="blogger-post-footer"&gt;&lt;img width='1' height='1' src='https://blogger.googleusercontent.com/tracker/652174954000901332-7222927740202947410?l=www.babel-lutefisk.net'/&gt;&lt;/div&gt;&lt;img src="http://feeds.feedburner.com/~r/BabelLutefisk/~4/89dEmGtsH5k" height="1" width="1"/&gt;</content><link rel="replies" type="application/atom+xml" href="http://www.babel-lutefisk.net/feeds/7222927740202947410/comments/default" title="Post Comments" /><link rel="replies" type="text/html" href="https://www.blogger.com/comment.g?blogID=652174954000901332&amp;postID=7222927740202947410" title="0 Comments" /><link rel="edit" type="application/atom+xml" href="http://www.blogger.com/feeds/652174954000901332/posts/default/7222927740202947410" /><link rel="self" type="application/atom+xml" href="http://www.blogger.com/feeds/652174954000901332/posts/default/7222927740202947410" /><link rel="alternate" type="text/html" href="http://feedproxy.google.com/~r/BabelLutefisk/~3/89dEmGtsH5k/im-on-bit-of-roll-with-agile-thinking.html" title="More and more about agility" /><author><name>Øyvind Valland</name><uri>http://www.blogger.com/profile/17595718624373482981</uri><email>noreply@blogger.com</email><gd:extendedProperty xmlns:gd="http://schemas.google.com/g/2005" name="OpenSocialUserId" value="18377601055500046677" /></author><thr:total xmlns:thr="http://purl.org/syndication/thread/1.0">0</thr:total><feedburner:origLink>http://www.babel-lutefisk.net/2008/07/im-on-bit-of-roll-with-agile-thinking.html</feedburner:origLink></entry><entry><id>tag:blogger.com,1999:blog-652174954000901332.post-4846833120522290368</id><published>2008-07-07T11:05:00.004+01:00</published><updated>2008-07-07T18:57:23.719+01:00</updated><category scheme="http://www.blogger.com/atom/ns#" term="Getting Real" /><category scheme="http://www.blogger.com/atom/ns#" term="Agility" /><title type="text">A few more words on agility.</title><content type="html">I wrote in &lt;a href="http://www.babel-lutefisk.net/2008/06/stay-agile-just-stay-agile.html"&gt;a post not long ago&lt;/a&gt; about the importance of staying agile in your development process, and I thought I'd elaborate a little further. I'm now involved in a project which is getting close to entering the development phase, and the last few weeks have highlighted to me where we go wrong and why we go wrong so often when we've got a good idea for software.&lt;br /&gt;&lt;br /&gt;The potential scope of the project I'm working on now is &lt;span style="font-style:italic;"&gt;huge&lt;/span&gt;. The idea itself is nothing new (I can't go into it here for obvious reasons) but the setting and the "take" on the idea is new, and probably better than what the competition has come up with. The guy that came up with the idea (my boss, let's call him M) soon realized that there is real money to be made in an emerging market, and he's received funding from the company board to set up a new department and get the project off the ground. Everybody is really excited about what's about to happen and everyone is "behind" the idea.&lt;br /&gt;&lt;br /&gt;All of that is really good and nobody's complaining. However, all this excitement lead to some problems right from the start. M's idea grew rapidly. Scope creep, anyone? More like scope avalanche/flood/torrent (choose your own appropriate natural disaster analogy). And everyone was still just as excited. Except me, probably. Part of my excitement started turning to fear. I saw that if this thing was allowed to take its natural course, we'd crash and burn. Because, quicker than you can say "Waterfall methodology" M (with my help) had mapped out a system so large and so complex that it simply wouldn't be possible to deliver it on time. It probably couldn't be developed in twice the allocated time. And when I pointed out the fact, things got really scary for a while.&lt;br /&gt;&lt;br /&gt;M was incredibly keen on "doing something" (I admire this man's energy and passion for his work, I really do). The business leaders thought the idea was brilliant and wanted it to happen, and happen now (heard that one before?). And the fact that there was too much work and not enough time could easily be overcome. The company makes good money these days, so we could have more allocated to our budget. &lt;br /&gt;&lt;br /&gt;More money equals more developers equals more lines of code in a day equals faster delivery. Right? I don't think so. In fact, I &lt;span style="font-style:italic;"&gt;know&lt;/span&gt; it doesn't work that way. And that's what I had to make M and the others see. Before _anything_ had been produced, the company was - potentially - ready to fork out huge amounts of money to back up a project that had done nothing to prove itself except look good on paper. So I put the brakes on. I spoke with M and expressed my concerns. I told him I thought it is incredibly risky to assume that we know everything about what our customers want and develop something so huge purely on a hunch. I told him we should keep the original deadline and pull back the scope so that we could hit the deadline safely. I told him we should limit the available resource and do as much as possible within the constraints of the original budget and resources available. I asked him to read 37Signals' &lt;a href="http://gettingreal.37signals.com/"&gt;"Getting Real"&lt;/a&gt;.&lt;br /&gt;&lt;br /&gt;And guess what? M skimmed through &lt;a href="http://gettingreal.37signals.com/"&gt;"Getting Real"&lt;/a&gt; and he got it. He understood the point of what I was saying. And so he slowed down.&lt;br /&gt;&lt;br /&gt;But the business didn't. They encouraged us to "think big". So we did. In a four day exercise we thought real big and put together numbers and estimates for what it would cost to deliver M's idea, scope creep and all, by the original deadline. And the cost came in at about ten times the budget for the first year. That kind of drove it home: It's a risky and really costly approach.&lt;br /&gt;&lt;br /&gt;It's a risky approach because there are too many assumptions, and the main assumption is that we know what the customer wants. In a new project such as this one, where everything hinges on the customer, you should assume as little as possible and instead &lt;span style="font-style:italic;"&gt;listen&lt;/span&gt; to what your customers want. Launch with as little effort as possible and be ready to change when your customers demand it. That way you'll have a project that can grow and adapt and be successful because it &lt;span style="font-style:italic;"&gt;deserves&lt;/span&gt; to be - not because it had amazing funding.&lt;br /&gt;&lt;br /&gt;So now we're starting small. Thankfully. And guess what? The first deliverable isn't even going to be an in-house development. We're looking at some third party solutions to launch part of the product and build the rest around that third party solution. That way we can build the product in bits and pieces and work it up as required while the out-of-the box solution we purchase takes care of our first deliverable.&lt;br /&gt;&lt;br /&gt;So the project is turning back to a more agile approach, and thank God for that. What these weeks have highlighted to me is that there is a very real and very palpable risk of getting carried away when you're working on something new and exciting. It's easy to forget to stop and evaluate what you're doing. And when enough people get excited about the same thing, crowd control becomes difficult. We must remind ourselves that the _idea_ is only the starting point, and in the end it is really the &lt;span style="font-style:italic;"&gt;execution&lt;/span&gt; that matters. &lt;br /&gt;&lt;br /&gt;What happened in the first few weeks of this project is that there was too much focus on the idea and not enough focus on the reality surrounding its execution. Hopefully we've adjusted that balance now, but I'm sure there will interesting times ahead because "speaking agile" and "doing agile" are two quite different things. And I'm sure I'll be writing more about it here.&lt;div class="blogger-post-footer"&gt;&lt;img width='1' height='1' src='https://blogger.googleusercontent.com/tracker/652174954000901332-4846833120522290368?l=www.babel-lutefisk.net'/&gt;&lt;/div&gt;&lt;img src="http://feeds.feedburner.com/~r/BabelLutefisk/~4/KNdmJqCVfQM" height="1" width="1"/&gt;</content><link rel="replies" type="application/atom+xml" href="http://www.babel-lutefisk.net/feeds/4846833120522290368/comments/default" title="Post Comments" /><link rel="replies" type="text/html" href="https://www.blogger.com/comment.g?blogID=652174954000901332&amp;postID=4846833120522290368" title="0 Comments" /><link rel="edit" type="application/atom+xml" href="http://www.blogger.com/feeds/652174954000901332/posts/default/4846833120522290368" /><link rel="self" type="application/atom+xml" href="http://www.blogger.com/feeds/652174954000901332/posts/default/4846833120522290368" /><link rel="alternate" type="text/html" href="http://feedproxy.google.com/~r/BabelLutefisk/~3/KNdmJqCVfQM/few-more-words-on-agility.html" title="A few more words on agility." /><author><name>Øyvind Valland</name><uri>http://www.blogger.com/profile/17595718624373482981</uri><email>noreply@blogger.com</email><gd:extendedProperty xmlns:gd="http://schemas.google.com/g/2005" name="OpenSocialUserId" value="18377601055500046677" /></author><thr:total xmlns:thr="http://purl.org/syndication/thread/1.0">0</thr:total><feedburner:origLink>http://www.babel-lutefisk.net/2008/07/few-more-words-on-agility.html</feedburner:origLink></entry><entry><id>tag:blogger.com,1999:blog-652174954000901332.post-6297520962739493453</id><published>2008-07-05T09:56:00.003+01:00</published><updated>2008-07-07T18:55:21.170+01:00</updated><category scheme="http://www.blogger.com/atom/ns#" term="Silverlight" /><category scheme="http://www.blogger.com/atom/ns#" term="Quality" /><title type="text">Quick update on the Silverlight plugin issue</title><content type="html">In a reply to a comment from &lt;a href="http://jonas.follesoe.no/"&gt;Jonas Follesø&lt;/a&gt; I wrote &lt;blockquote&gt;Also, having installed the Silverlight 2 plugin, I find that several of the Silverlight 1 sites from the Silverlight.net showcase either do not work (I'm prompted to install Silverlight!) or work intermittently. This doesn't give me a lot of confidence in the technology right now.&lt;/blockquote&gt; Jonas followed up with a &lt;a href="http://timheuer.com/blog/archive/2008/07/02/updating-your-silverlight-javascript-detection.aspx"&gt;link&lt;/a&gt; about this particular issue. Turns out Firefox 3 isn't yet a supported browser!&lt;div class="blogger-post-footer"&gt;&lt;img width='1' height='1' src='https://blogger.googleusercontent.com/tracker/652174954000901332-6297520962739493453?l=www.babel-lutefisk.net'/&gt;&lt;/div&gt;&lt;img src="http://feeds.feedburner.com/~r/BabelLutefisk/~4/HzzVB9qwLVk" height="1" width="1"/&gt;</content><link rel="replies" type="application/atom+xml" href="http://www.babel-lutefisk.net/feeds/6297520962739493453/comments/default" title="Post Comments" /><link rel="replies" type="text/html" href="https://www.blogger.com/comment.g?blogID=652174954000901332&amp;postID=6297520962739493453" title="0 Comments" /><link rel="edit" type="application/atom+xml" href="http://www.blogger.com/feeds/652174954000901332/posts/default/6297520962739493453" /><link rel="self" type="application/atom+xml" href="http://www.blogger.com/feeds/652174954000901332/posts/default/6297520962739493453" /><link rel="alternate" type="text/html" href="http://feedproxy.google.com/~r/BabelLutefisk/~3/HzzVB9qwLVk/quick-update-on-silverlight-plugin.html" title="Quick update on the Silverlight plugin issue" /><author><name>Øyvind Valland</name><uri>http://www.blogger.com/profile/17595718624373482981</uri><email>noreply@blogger.com</email><gd:extendedProperty xmlns:gd="http://schemas.google.com/g/2005" name="OpenSocialUserId" value="18377601055500046677" /></author><thr:total xmlns:thr="http://purl.org/syndication/thread/1.0">0</thr:total><feedburner:origLink>http://www.babel-lutefisk.net/2008/07/quick-update-on-silverlight-plugin.html</feedburner:origLink></entry><entry><id>tag:blogger.com,1999:blog-652174954000901332.post-8282497481530496283</id><published>2008-07-03T12:03:00.004+01:00</published><updated>2008-07-07T18:55:38.691+01:00</updated><category scheme="http://www.blogger.com/atom/ns#" term="Silverlight" /><category scheme="http://www.blogger.com/atom/ns#" term="Quality" /><title type="text">Silverlight plugin trouble</title><content type="html">How can Silverlight expect to take over the world when there are such serious compatibility issues between the plugin's version 1 and 2? I upgraded my plugin in IE, but not in FireFox. Now FireFox crashes, just simply &lt;span style="font-style:italic;"&gt;dies&lt;/span&gt; whenever I try to go to a site with embedded Silverlight 2 content. Whether this is a FireFox 3 issue or a Silverlight issue I cannot state categorically - but it's a big issue and seriously detracts from the appeal of building apps with Silverlight 2. I'm also a bit worried about the size of the new plugin. &lt;span style="font-weight:bold;"&gt;4.7MB&lt;span style="font-style:italic;"&gt;!!&lt;/span&gt;&lt;/span&gt; That's &lt;span style="font-style:italic;"&gt;3.3MB&lt;/span&gt; up on version 1. Not a good trend.&lt;div class="blogger-post-footer"&gt;&lt;img width='1' height='1' src='https://blogger.googleusercontent.com/tracker/652174954000901332-8282497481530496283?l=www.babel-lutefisk.net'/&gt;&lt;/div&gt;&lt;img src="http://feeds.feedburner.com/~r/BabelLutefisk/~4/CNXw5lrQToE" height="1" width="1"/&gt;</content><link rel="replies" type="application/atom+xml" href="http://www.babel-lutefisk.net/feeds/8282497481530496283/comments/default" title="Post Comments" /><link rel="replies" type="text/html" href="https://www.blogger.com/comment.g?blogID=652174954000901332&amp;postID=8282497481530496283" title="3 Comments" /><link rel="edit" type="application/atom+xml" href="http://www.blogger.com/feeds/652174954000901332/posts/default/8282497481530496283" /><link rel="self" type="application/atom+xml" href="http://www.blogger.com/feeds/652174954000901332/posts/default/8282497481530496283" /><link rel="alternate" type="text/html" href="http://feedproxy.google.com/~r/BabelLutefisk/~3/CNXw5lrQToE/silverlight-plugin-trouble.html" title="Silverlight plugin trouble" /><author><name>Øyvind Valland</name><uri>http://www.blogger.com/profile/17595718624373482981</uri><email>noreply@blogger.com</email><gd:extendedProperty xmlns:gd="http://schemas.google.com/g/2005" name="OpenSocialUserId" value="18377601055500046677" /></author><thr:total xmlns:thr="http://purl.org/syndication/thread/1.0">3</thr:total><feedburner:origLink>http://www.babel-lutefisk.net/2008/07/silverlight-plugin-trouble.html</feedburner:origLink></entry></feed>
