<?xml version='1.0' encoding='UTF-8'?><?xml-stylesheet href="http://www.blogger.com/styles/atom.css" type="text/css"?><feed xmlns='http://www.w3.org/2005/Atom' xmlns:openSearch='http://a9.com/-/spec/opensearchrss/1.0/' xmlns:georss='http://www.georss.org/georss' xmlns:gd='http://schemas.google.com/g/2005' xmlns:thr='http://purl.org/syndication/thread/1.0'><id>tag:blogger.com,1999:blog-5984183628613054769</id><updated>2011-04-21T22:08:52.444+01:00</updated><title type='text'>Sarah Taraporewalla's Technical Ramblings</title><subtitle type='html'>This is my technical blog, where I will be dumping my current thoughts on all things agile, web related or where ever my mood takes me.

I am a software consultant at Thoughtworks, currently based in London.</subtitle><link rel='http://schemas.google.com/g/2005#feed' type='application/atom+xml' href='http://sarahtaraporewalla.blogspot.com/feeds/posts/default'/><link rel='self' type='application/atom+xml' href='http://www.blogger.com/feeds/5984183628613054769/posts/default?max-results=100'/><link rel='alternate' type='text/html' href='http://sarahtaraporewalla.blogspot.com/'/><link rel='hub' href='http://pubsubhubbub.appspot.com/'/><author><name>Sarah Taraporewalla</name><uri>http://www.blogger.com/profile/06551171381021637312</uri><email>noreply@blogger.com</email><gd:image rel='http://schemas.google.com/g/2005#thumbnail' width='16' height='16' src='http://img2.blogblog.com/img/b16-rounded.gif'/></author><generator version='7.00' uri='http://www.blogger.com'>Blogger</generator><openSearch:totalResults>9</openSearch:totalResults><openSearch:startIndex>1</openSearch:startIndex><openSearch:itemsPerPage>100</openSearch:itemsPerPage><entry><id>tag:blogger.com,1999:blog-5984183628613054769.post-6474459079937478976</id><published>2008-09-30T13:19:00.002+01:00</published><updated>2008-09-30T13:20:35.966+01:00</updated><title type='text'>This blog has now moved</title><content type='html'>This blog has now been moved to:&lt;br /&gt;http://sarahtaraporewalla.com&lt;br /&gt;&lt;br /&gt;You can subscribe to the feed:&lt;br /&gt;http://feeds.feedburner.com/sarahtaraporewalla&lt;div class="blogger-post-footer"&gt;&lt;img width='1' height='1' src='https://blogger.googleusercontent.com/tracker/5984183628613054769-6474459079937478976?l=sarahtaraporewalla.blogspot.com' alt='' /&gt;&lt;/div&gt;</content><link rel='replies' type='application/atom+xml' href='http://sarahtaraporewalla.blogspot.com/feeds/6474459079937478976/comments/default' title='Post Comments'/><link rel='replies' type='text/html' href='http://www.blogger.com/comment.g?blogID=5984183628613054769&amp;postID=6474459079937478976' title='0 Comments'/><link rel='edit' type='application/atom+xml' href='http://www.blogger.com/feeds/5984183628613054769/posts/default/6474459079937478976'/><link rel='self' type='application/atom+xml' href='http://www.blogger.com/feeds/5984183628613054769/posts/default/6474459079937478976'/><link rel='alternate' type='text/html' href='http://sarahtaraporewalla.blogspot.com/2008/09/this-blog-has-now-moved.html' title='This blog has now moved'/><author><name>Sarah Taraporewalla</name><uri>http://www.blogger.com/profile/06551171381021637312</uri><email>noreply@blogger.com</email><gd:image rel='http://schemas.google.com/g/2005#thumbnail' width='16' height='16' src='http://img2.blogblog.com/img/b16-rounded.gif'/></author><thr:total>0</thr:total></entry><entry><id>tag:blogger.com,1999:blog-5984183628613054769.post-875086945005509483</id><published>2008-09-24T07:45:00.003+01:00</published><updated>2008-09-24T08:01:48.501+01:00</updated><title type='text'>How many O's in Woolloomooloo*</title><content type='html'>&lt;div&gt;I am often asked how to pronounce my surname. It's not too difficult, but for your benefit, I will now attempt at a phonetic guide to my last name. &lt;/div&gt;&lt;div&gt;Essentially, it can be broken down into 3 parts: &lt;span class="Apple-style-span" style="font-style: italic;"&gt;tara&lt;/span&gt; - &lt;span class="Apple-style-span" style="font-style: italic;"&gt;pore&lt;/span&gt; - &lt;span class="Apple-style-span" style="font-style: italic;"&gt;walla**&lt;/span&gt;. &lt;/div&gt;&lt;div&gt;&lt;br /&gt;&lt;/div&gt;&lt;div&gt;&lt;span class="Apple-style-span" style="font-style: italic;"&gt;Tara&lt;/span&gt;&lt;/div&gt;&lt;div&gt;pronounced ta-ra. Like the girls name; like the house in Gone With The Wind (but without Vivian Leigh's accent please.)&lt;/div&gt;&lt;div&gt;&lt;br /&gt;&lt;/div&gt;&lt;div&gt;&lt;span class="Apple-style-span" style="font-style: italic;"&gt;Pore&lt;/span&gt;&lt;/div&gt;&lt;div&gt;pronounced like pour or poor. The 'e' is silent.&lt;/div&gt;&lt;div&gt;&lt;br /&gt;&lt;/div&gt;&lt;div&gt;&lt;span class="Apple-style-span" style="font-style: italic;"&gt;Walla&lt;/span&gt;&lt;/div&gt;&lt;div&gt;pronounced wa-lla. Not wall-a.&lt;/div&gt;&lt;div&gt;&lt;br /&gt;&lt;/div&gt;&lt;div&gt;&lt;br /&gt;&lt;/div&gt;&lt;div&gt;Put it all together and you get : &lt;span class="Apple-style-span" style="font-style: italic;"&gt;ta&lt;/span&gt;-&lt;span class="Apple-style-span" style="font-style: italic;"&gt;ra&lt;/span&gt;-&lt;span class="Apple-style-span" style="font-style: italic;"&gt;pour&lt;/span&gt;-&lt;span class="Apple-style-span" style="font-style: italic;"&gt;wa&lt;/span&gt;-&lt;span class="Apple-style-span" style="font-style: italic;"&gt;la&lt;/span&gt;&lt;/div&gt;&lt;div&gt;&lt;span class="Apple-style-span" style="font-style: italic;"&gt;&lt;br /&gt;&lt;/span&gt;&lt;/div&gt;&lt;div&gt;I hope that helps. &lt;/div&gt;&lt;div&gt;&lt;br /&gt;&lt;/div&gt;&lt;div&gt;Please feel free to let me know how you thought it was pronounced or spelt.  &lt;/div&gt;&lt;div&gt;&lt;br /&gt;&lt;/div&gt;&lt;div&gt;&lt;br /&gt;&lt;/div&gt;* &lt;span class="Apple-style-span"  style="font-size:small;"&gt;The title of this post comes from a riddle by C.J.Dennis:&lt;/span&gt;&lt;div&gt;&lt;span class="Apple-style-span"  style="font-size:small;"&gt;How many O's in Woolloomooloo?&lt;/span&gt;&lt;/div&gt;&lt;div&gt;&lt;span class="Apple-style-span"  style="font-size:small;"&gt;Two for the W, two for the M&lt;/span&gt;&lt;/div&gt;&lt;div&gt;&lt;span class="Apple-style-span"  style="font-size:small;"&gt;Four for the Ls and thats plenty of them.&lt;/span&gt;&lt;/div&gt;&lt;div&gt;&lt;span class="Apple-style-span"  style="font-size:small;"&gt;(Woolloomoloo is a suburb of Sydney, Australia)&lt;/span&gt;&lt;/div&gt;&lt;div&gt;&lt;span class="Apple-style-span"  style="font-size:13px;"&gt;&lt;br /&gt;&lt;/span&gt;&lt;/div&gt;&lt;div&gt;&lt;span class="Apple-style-span"  style="font-size:13px;"&gt;** Oh - and I have one vowel for every consonant (I always lump the double Ls together)&lt;/span&gt;&lt;/div&gt;&lt;div class="blogger-post-footer"&gt;&lt;img width='1' height='1' src='https://blogger.googleusercontent.com/tracker/5984183628613054769-875086945005509483?l=sarahtaraporewalla.blogspot.com' alt='' /&gt;&lt;/div&gt;</content><link rel='replies' type='application/atom+xml' href='http://sarahtaraporewalla.blogspot.com/feeds/875086945005509483/comments/default' title='Post Comments'/><link rel='replies' type='text/html' href='http://www.blogger.com/comment.g?blogID=5984183628613054769&amp;postID=875086945005509483' title='0 Comments'/><link rel='edit' type='application/atom+xml' href='http://www.blogger.com/feeds/5984183628613054769/posts/default/875086945005509483'/><link rel='self' type='application/atom+xml' href='http://www.blogger.com/feeds/5984183628613054769/posts/default/875086945005509483'/><link rel='alternate' type='text/html' href='http://sarahtaraporewalla.blogspot.com/2008/09/how-many-os-in-woolloomooloo.html' title='How many O&apos;s in Woolloomooloo*'/><author><name>Sarah Taraporewalla</name><uri>http://www.blogger.com/profile/06551171381021637312</uri><email>noreply@blogger.com</email><gd:image rel='http://schemas.google.com/g/2005#thumbnail' width='16' height='16' src='http://img2.blogblog.com/img/b16-rounded.gif'/></author><thr:total>0</thr:total></entry><entry><id>tag:blogger.com,1999:blog-5984183628613054769.post-2361786373565557849</id><published>2008-09-11T07:32:00.003+01:00</published><updated>2008-09-11T13:29:16.974+01:00</updated><title type='text'>ReSharper - Saint or Sinner</title><content type='html'>I love &lt;a href="http://www.jetbrains.com/resharper/"&gt;ReSharper&lt;/a&gt;. It makes life in Visual Studio such a breeze. You are just so productive in it, with all of its navigation tools, code completion and automatic refactorings. I tried to use Visual Studio without ReSharper the other day - it was so impeded that I swapped computers after about 5 minutes work (mind you - when I swapped, I redid the work in about 30sec). &lt;div&gt;&lt;br /&gt;&lt;/div&gt;&lt;div&gt;But, sometimes I think ReSharper makes you, the developer, dumber. Or maybe not so much dumber, but definitely less in control of the code, and therefore  makes the code wild and messy.&lt;/div&gt;&lt;div&gt;&lt;br /&gt;&lt;/div&gt;&lt;div&gt;Before I used ReSharper, I had quite a lot of information about the code base in my head. I knew how classes connected, which files and namespaces they belonged to, what the model looked like. A file rarely got too long, because that would mean I would have to scroll through the file to look for my desired class. If something had changed within a class, like the addition of new methods, I would recognize it quickly regardless of whether it was in the code path I was following.&lt;/div&gt;&lt;div&gt;&lt;br /&gt;&lt;/div&gt;&lt;div&gt;Now, I only find new features when I actively look for them. I find files that are quite long  because I never look at the whole file, only the method that ReSharper brought me to when I used it to navigate a code path. I can't describe how the classes are connected, what namespace or class individual methods are in. And the reason - because I gave ReSharper the power. I stopped being in charge of the code. I stopped inspecting the code base.&lt;/div&gt;&lt;div&gt;&lt;br /&gt;&lt;/div&gt;&lt;div&gt;&lt;br /&gt;&lt;/div&gt;&lt;div&gt;Are we too becoming lazy? Are we reverting back into old, bad practices because ReSharper makes it just so darn easy to use? Are we becoming dumber?&lt;/div&gt;&lt;div class="blogger-post-footer"&gt;&lt;img width='1' height='1' src='https://blogger.googleusercontent.com/tracker/5984183628613054769-2361786373565557849?l=sarahtaraporewalla.blogspot.com' alt='' /&gt;&lt;/div&gt;</content><link rel='replies' type='application/atom+xml' href='http://sarahtaraporewalla.blogspot.com/feeds/2361786373565557849/comments/default' title='Post Comments'/><link rel='replies' type='text/html' href='http://www.blogger.com/comment.g?blogID=5984183628613054769&amp;postID=2361786373565557849' title='2 Comments'/><link rel='edit' type='application/atom+xml' href='http://www.blogger.com/feeds/5984183628613054769/posts/default/2361786373565557849'/><link rel='self' type='application/atom+xml' href='http://www.blogger.com/feeds/5984183628613054769/posts/default/2361786373565557849'/><link rel='alternate' type='text/html' href='http://sarahtaraporewalla.blogspot.com/2008/09/resharper-saint-or-sinner.html' title='ReSharper - Saint or Sinner'/><author><name>Sarah Taraporewalla</name><uri>http://www.blogger.com/profile/06551171381021637312</uri><email>noreply@blogger.com</email><gd:image rel='http://schemas.google.com/g/2005#thumbnail' width='16' height='16' src='http://img2.blogblog.com/img/b16-rounded.gif'/></author><thr:total>2</thr:total></entry><entry><id>tag:blogger.com,1999:blog-5984183628613054769.post-8021938050948132042</id><published>2008-09-07T10:48:00.005+01:00</published><updated>2008-09-07T11:52:01.608+01:00</updated><title type='text'>Say the right thing - don't just do the right thing.</title><content type='html'>Often, I see tests like the following:&lt;div&gt;&lt;br /&gt;&lt;pre&gt;&lt;br /&gt;public void SuccessulUpdateOfCarDeatilsShouldReturnSuccessResponse()&lt;br /&gt;{&lt;br /&gt; CarController controller = new CarController()&lt;br /&gt; &lt;br /&gt; controller.UpdateCarDetails(0, string.empty, string.empty, string.empty)&lt;br /&gt; &lt;br /&gt; Assert.AreEqual(200, controller.Response)&lt;br /&gt;}&lt;br /&gt;&lt;/pre&gt;&lt;br /&gt;&lt;/div&gt;&lt;div&gt;This conveys to me two things about the author of the test:&lt;/div&gt;&lt;div&gt;&lt;ol&gt;&lt;li&gt;They treat tests as second-class citizens&lt;/li&gt;&lt;li&gt;They have no respect for me, the unknown reader of the test&lt;/li&gt;&lt;/ol&gt;&lt;div&gt;Let me explain. I could be viewing these tests for a variety of reasons - to add new tests as bugs have appeared, to alter the functionality of the unit-under-test, to understand the unit-under-test ... etc.&lt;/div&gt;&lt;div&gt;&lt;br /&gt;&lt;/div&gt;&lt;div&gt;Before I can understand what the test is actually testing, I need to look at the signature of the class (ie open the file, navigate to the constructor...) to determine what the string.empty and zeros are representing.  This takes extra effort on my part to understand the intent of the test*.&lt;br /&gt;&lt;pre&gt;&lt;br /&gt;public class CarController&lt;br /&gt;{&lt;br /&gt; ...&lt;br /&gt; public void UpdateCarDeatils(int carId, string carRegistration, string colour, string engineIdentificationNumber)&lt;br /&gt; {&lt;br /&gt;  ...&lt;br /&gt; }&lt;br /&gt;}&lt;br /&gt;&lt;/pre&gt;&lt;br /&gt;&lt;/div&gt;&lt;div&gt;&lt;br /&gt;&lt;/div&gt;&lt;div&gt;It also makes life difficult, because I am not sure if they are there for a particular purpose (ie the test is testing how the method handles nulls/empty strings) or if they are there because the author thinks they they are unimportant to the test. &lt;/div&gt;&lt;div&gt;&lt;br /&gt;&lt;/div&gt;&lt;div&gt;I prefer to explicitly call out my unimportant parameters, by passing realistic but dummy values. I would rework the above example into:&lt;/div&gt;&lt;div&gt;&lt;br /&gt;&lt;pre&gt;&lt;br /&gt;public void SuccessulUpdateOfCarDeatilsShouldReturnSuccessResponse()&lt;br /&gt;{&lt;br /&gt; CarController controller = new CarController()&lt;br /&gt; &lt;br /&gt; controller.UpdateCarDetails(42, "car registration", "colour", "engineIdentificationNumber")&lt;br /&gt; &lt;br /&gt; Assert.AreEqual(200, controller.Response)&lt;br /&gt;}&lt;br /&gt;&lt;/pre&gt;&lt;br /&gt;&lt;/div&gt;&lt;div&gt;&lt;br /&gt;&lt;/div&gt;&lt;div&gt;This way I can see at a simple glance at the one test file what the method expects to take as parameters. I tend to use &lt;a href="http://en.wikipedia.org/wiki/Answer_to_Life,_the_Universe,_and_Everything"&gt;42&lt;/a&gt; as my default dummy id value, so when my team mates see it, they know it is an id value (zero is often an indicator of an object which is not persisted).&lt;/div&gt;&lt;div&gt;&lt;br /&gt;&lt;/div&gt;&lt;div&gt;By replacing the meaningless empty values, with meaningless values which explain themselves you run into less problems adding the new tests, refactoring or altering functionality as the reader understands the intent of the test. Now, the test not only &lt;span class="Apple-style-span" style="font-style: italic;"&gt;does&lt;/span&gt; the right thing, but also &lt;span class="Apple-style-span" style="font-style: italic;"&gt;says&lt;/span&gt; the right thing.&lt;/div&gt;&lt;div&gt;&lt;br /&gt;&lt;/div&gt;&lt;div&gt;*Even with Intelli-J or Resharper, there is work involved to understand these values&lt;/div&gt;&lt;/div&gt;&lt;div class="blogger-post-footer"&gt;&lt;img width='1' height='1' src='https://blogger.googleusercontent.com/tracker/5984183628613054769-8021938050948132042?l=sarahtaraporewalla.blogspot.com' alt='' /&gt;&lt;/div&gt;</content><link rel='replies' type='application/atom+xml' href='http://sarahtaraporewalla.blogspot.com/feeds/8021938050948132042/comments/default' title='Post Comments'/><link rel='replies' type='text/html' href='http://www.blogger.com/comment.g?blogID=5984183628613054769&amp;postID=8021938050948132042' title='1 Comments'/><link rel='edit' type='application/atom+xml' href='http://www.blogger.com/feeds/5984183628613054769/posts/default/8021938050948132042'/><link rel='self' type='application/atom+xml' href='http://www.blogger.com/feeds/5984183628613054769/posts/default/8021938050948132042'/><link rel='alternate' type='text/html' href='http://sarahtaraporewalla.blogspot.com/2008/09/say-right-thing-dont-just-do-right.html' title='Say the right thing - don&apos;t just do the right thing.'/><author><name>Sarah Taraporewalla</name><uri>http://www.blogger.com/profile/06551171381021637312</uri><email>noreply@blogger.com</email><gd:image rel='http://schemas.google.com/g/2005#thumbnail' width='16' height='16' src='http://img2.blogblog.com/img/b16-rounded.gif'/></author><thr:total>1</thr:total></entry><entry><id>tag:blogger.com,1999:blog-5984183628613054769.post-4224511914228784012</id><published>2008-08-26T15:41:00.000+01:00</published><updated>2008-09-03T08:11:22.761+01:00</updated><title type='text'>Test names go wild</title><content type='html'>&lt;div&gt;&lt;span class="Apple-style-span" style="font-weight: bold;"&gt;&lt;span class="Apple-style-span"  style=" font-weight: normal; font-family:Times;"&gt;&lt;div style="border-top-width: 0px; border-right-width: 0px; border-bottom-width: 0px; border-left-width: 0px; border-style: initial; border-color: initial; margin-top: 0px; margin-right: 0px; margin-bottom: 0px; margin-left: 0px; padding-top: 3px; padding-right: 3px; padding-bottom: 3px; padding-left: 3px; width: auto; font: normal normal normal 100%/normal Georgia, serif; text-align: left; "&gt;Around &lt;a href="http://www.thoughtworks.com/"&gt;Thoughtworks&lt;/a&gt;, there is much discussion about test strategies. The arguments range from setup vs inline; named vs anonymous; mocks vs stubs; high level vs unit level, and everyone has their own preferred techniques. While a lot of people talk about the virtues of either side, I wanted to talk about using test names wisely.&lt;div&gt;&lt;br /&gt;I have worked with &lt;a href="http://blog.jayfields.com/"&gt;Jay Fields&lt;/a&gt;, a man who is quite passionate about tests. His blog has a whole stream of entries around testing. One post which I believe caused a bit of a stir was his entry on &lt;a href="http://blog.jayfields.com/2008/05/testing-value-of-test-names.html"&gt;the value of test names. &lt;/a&gt;&lt;/div&gt;&lt;div&gt;&lt;br /&gt;&lt;/div&gt;&lt;div&gt;I understand where he is coming from, and if you are fortunate to be writing in Ruby, then your testing battles are half won already. If you use the gems like &lt;a href="http://mocha.rubyforge.org/"&gt;mocha&lt;/a&gt; and &lt;a href="http://expectations.rubyforge.org/"&gt;expectations&lt;/a&gt;, then testing is so natural, that you do end up with 2 to 3 line tests, &lt;a href="http://blog.jayfields.com/2007/06/testing-one-assertion-per-test.html"&gt;one assertion per test&lt;/a&gt; and there isn't a need for test names because everything is so neat and understandable, that they become clutter. &lt;/div&gt;&lt;div&gt;&lt;br /&gt;&lt;/div&gt;&lt;div&gt;However, if you are in a language like C# (which is what my current project is in) then testing becomes that little bit harder, a little more like running through treacle. Mocking is one example of this - compare &lt;a href="http://www.nmock.org/"&gt;NMock&lt;/a&gt; to mocha... well, actually don't bother because they can't compare. Mocha beats NMock hands down. On my current project, I started to use mocks as I would on another ruby-based project, and quickly switched to stubbed classes because it was lacking in far too many places. &lt;/div&gt;&lt;div&gt;&lt;br /&gt;&lt;/div&gt;&lt;div&gt;So, sometimes your environments dictate which testing strategy you should use. But here is my plea - if you use test names, please oh please treat them with the same respect as you treat your method names.  &lt;/div&gt;&lt;div&gt;&lt;br /&gt;&lt;/div&gt;&lt;div&gt;My biggest problem with test names is that they may be perfectly fine when you write the code for the first time, but then sometime later someone starts refactoring the code base. Tests start failing (perhaps the requirements have changed, so the test failures are a good thing) and you fix the failing test...but not the test name. And so, a little while later you have a test which is similar to this very trivial example (and yes, I have seen tests like this):&lt;/div&gt;&lt;div&gt;&lt;pre&gt;public void ShouldContainOrderedListOfClients()&lt;br /&gt;{&lt;br /&gt; Event first = new Event("AAA")&lt;br /&gt; Event second = new Event("ZZZ")&lt;br /&gt; Event[] result = Order(first, second)&lt;br /&gt; Assert.AreEqual(first, result[0])&lt;br /&gt; Assert.AreEqual(second, result[0])&lt;br /&gt;}&lt;br /&gt;&lt;/pre&gt;&lt;br /&gt;&lt;/div&gt;&lt;div&gt;Hang on - what the...? That test name has nothing to do with what is being tested. But which is correct - the test name or the test itself. And has there been a test which is now lost? Or has it moved? What is the source of truth? &lt;/div&gt;&lt;div&gt;&lt;br /&gt;&lt;/div&gt;&lt;div&gt;Sometimes, knowing what the requirements for the unit in question are should be enough to fix up the offending item. Sometimes they are not. &lt;/div&gt;&lt;div&gt;&lt;br /&gt;&lt;/div&gt;&lt;div&gt;My take home advice - think about what your test is doing before you begin to write the test. Perhaps you even write the names for 4 tests at once, before implementing any of them. That way you can focus on the test at hand,  you don't have to be thinking of testing a whole variety of cases in the one test and your tests become small enough that you can easily identify when the test name differs from the test at hand.&lt;/div&gt;&lt;div&gt;&lt;br /&gt;&lt;/div&gt;&lt;div&gt;Also, treat your test code not as a second class citizen, but as important, if not more important than your code. Tests give you a confidence in the application you are building. To increase your confidence in your tests, you need to increase the time you spend refactoring them and making sure they are testing exactly what they say they are testing, and that there are no holes where your code can fall through and fail.  &lt;/div&gt;&lt;div&gt;&lt;br /&gt;&lt;/div&gt;&lt;div&gt;&lt;br /&gt;&lt;/div&gt;&lt;/div&gt;&lt;/span&gt;&lt;/span&gt;&lt;/div&gt;&lt;div class="blogger-post-footer"&gt;&lt;img width='1' height='1' src='https://blogger.googleusercontent.com/tracker/5984183628613054769-4224511914228784012?l=sarahtaraporewalla.blogspot.com' alt='' /&gt;&lt;/div&gt;</content><link rel='replies' type='application/atom+xml' href='http://sarahtaraporewalla.blogspot.com/feeds/4224511914228784012/comments/default' title='Post Comments'/><link rel='replies' type='text/html' href='http://www.blogger.com/comment.g?blogID=5984183628613054769&amp;postID=4224511914228784012' title='3 Comments'/><link rel='edit' type='application/atom+xml' href='http://www.blogger.com/feeds/5984183628613054769/posts/default/4224511914228784012'/><link rel='self' type='application/atom+xml' href='http://www.blogger.com/feeds/5984183628613054769/posts/default/4224511914228784012'/><link rel='alternate' type='text/html' href='http://sarahtaraporewalla.blogspot.com/2008/08/test-names-go-wild.html' title='Test names go wild'/><author><name>Sarah Taraporewalla</name><uri>http://www.blogger.com/profile/06551171381021637312</uri><email>noreply@blogger.com</email><gd:image rel='http://schemas.google.com/g/2005#thumbnail' width='16' height='16' src='http://img2.blogblog.com/img/b16-rounded.gif'/></author><thr:total>3</thr:total></entry><entry><id>tag:blogger.com,1999:blog-5984183628613054769.post-8265936050440759883</id><published>2008-08-16T08:56:00.000+01:00</published><updated>2008-08-16T14:24:44.332+01:00</updated><title type='text'>Lists: Filter, Map and Reduce</title><content type='html'>&lt;div&gt;There are 3 very handy list functions which make dealing with lists a breeze: Map, Filter and Reduce. I have come to the belief that not everyone understands their power, so I will attempt to explain it.&lt;/div&gt;&lt;div&gt;&lt;br /&gt;&lt;/div&gt;&lt;h3&gt;Filter&lt;/h3&gt;&lt;div&gt;The filter function  (fairly aptly named) aims to filter out (remove) items from the list which are not wanted. Typically, the Filter will take a list to be filtered and a condition to be met. Filter will then iterate through the list, and check each item in the list against the condition and form a new list from the items which pass the condition. A practical example would be: you have a list of names, and from that list you want the names that start with "S", so ["Snowy", "Shelly", "Muffin", "Oberon"] would filter to ["Snowy", "Shelly"].&lt;br /&gt;&lt;/div&gt;&lt;div&gt;&lt;br /&gt;&lt;pre&gt;&lt;br /&gt;public bool FilterFunction&lt;t&gt;(T item){&lt;br /&gt; return item.StartsWith("S")&lt;br /&gt;}&lt;br /&gt;public List&lt;t&gt; Filter&lt;t&gt;(List&lt;t&gt; list, FilterFunction&lt;t&gt; condition) {&lt;br /&gt; List&lt;t&gt; filteredList = new List&lt;t&gt;()&lt;br /&gt; foreach (T item in list) {&lt;br /&gt;  if (condition(item)){&lt;br /&gt;   filteredList.Add(item)&lt;br /&gt;  }&lt;br /&gt; }&lt;br /&gt; return filteredList&lt;br /&gt;}&lt;br /&gt;&lt;/t&gt;&lt;/t&gt;&lt;/t&gt;&lt;/t&gt;&lt;/t&gt;&lt;/t&gt;&lt;/t&gt;&lt;/pre&gt;&lt;br /&gt;&lt;/div&gt;&lt;div&gt;&lt;br /&gt;&lt;/div&gt;&lt;h3&gt;Map&lt;/h3&gt;&lt;div&gt;The map function takes a list and a function and applies the function to every item in the list. A practical example would be: a repository returns a list of Cars, but you need to have a list of the number of seats in the car, so [GWiz, SmartCar, CleverCityCar, PeopleMover] would map to [1, 2, 5, 9]. &lt;/div&gt;&lt;br /&gt;&lt;div&gt;&lt;br /&gt;&lt;pre&gt;&lt;br /&gt;public R MapFunction&lt;t, r=""&gt;(T item){&lt;br /&gt; return item.NumberOfSeats()&lt;br /&gt;}&lt;br /&gt;public List&lt;r&gt; Map&lt;t, r=""&gt;(List&lt;t&gt; list, MapFunction&lt;t, r=""&gt; mapFunction) {&lt;br /&gt; List&lt;r&gt; mappedList = new List&lt;r&gt;()&lt;br /&gt; foreach (T item in list) {&lt;br /&gt;  mappedList.Add(mapFunction(item))&lt;br /&gt; }&lt;br /&gt; return mappedList&lt;br /&gt;}&lt;br /&gt;&lt;/r&gt;&lt;/r&gt;&lt;/t,&gt;&lt;/t&gt;&lt;/t,&gt;&lt;/r&gt;&lt;/t,&gt;&lt;/pre&gt;&lt;br /&gt;&lt;/div&gt;&lt;br /&gt;&lt;h3&gt;Reduce&lt;/h3&gt;&lt;div&gt;Reduce is the hardest list function to understand (and explain). It is sometimes referred to as accumulate, fold, compress or inject. In effect, it takes the list and folds/compresses/reduces it down to a single value. Reduce takes a list and a function. It iterates over the list; it applies the function to the first item and a 'starting value'. The result of the first function will be used as the 'starting value' in the function of the next iteration. (Some implementations do not require a starting value, but start iterating over the second item in the list, using the first item as the starting value). A practical example would be: finding the total number of seats available in a set of cars, so using the example before of [GWiz, SmartCar, CleverCityCar, PeopleMover], the result would be 17 (1 + 2 + 5 + 9).  The common example you will see regarding this function is finding the total of all the numbers in a list, so [1, 2, 5, 9] would yield 17.&lt;/div&gt;&lt;div&gt;&lt;br /&gt;&lt;pre&gt;&lt;br /&gt;public R ReduceFunction&lt;t, r=""&gt;(T item, R accumalator){&lt;br /&gt; return item.NumberOfSeats + accumalator&lt;br /&gt;}&lt;br /&gt;public R Reduce&lt;t, r=""&gt;(List&lt;t&gt; list, ReduceFunction&lt;t, r=""&gt; reduceFunction, R startingValue) {&lt;br /&gt; R accumalator = startingValue&lt;br /&gt; foreach (T item in list) {&lt;br /&gt;  accumalator = reduceFunction(item, accumalator)&lt;br /&gt; }&lt;br /&gt; return accumalator&lt;br /&gt;}&lt;br /&gt;&lt;/t,&gt;&lt;/t&gt;&lt;/t,&gt;&lt;/t,&gt;&lt;/pre&gt;&lt;br /&gt;&lt;/div&gt;&lt;br /&gt;&lt;h3&gt;Summary&lt;/h3&gt;&lt;div&gt;The filter function transforms &lt;span class="Apple-style-span" style="font-style: italic;"&gt;a set &lt;/span&gt;(list) of items into &lt;span class="Apple-style-span" style="font-style: italic;"&gt;a subset&lt;/span&gt; of the items. &lt;/div&gt;&lt;div&gt;The map function transforms a list of items in &lt;span class="Apple-style-span" style="font-style: italic;"&gt;one type&lt;/span&gt; to a list of items in &lt;span class="Apple-style-span" style="font-style: italic;"&gt;another type&lt;/span&gt;.&lt;/div&gt;&lt;div&gt;The reduce function transforms &lt;span class="Apple-style-span" style="font-style: italic;"&gt;a list&lt;/span&gt; of items in one type to &lt;span class="Apple-style-span" style="font-style: italic;"&gt;an object&lt;/span&gt; in another type.&lt;/div&gt;&lt;div&gt;&lt;br /&gt;&lt;/div&gt;&lt;div&gt;Both Ruby and Python make excellent use of these functions, so if you would like to further your understanding, I would suggest using these.&lt;/div&gt;&lt;div&gt;I am lead to believe that C# has these functions, but only for array implementations (and definitely not on IList). I don't believe Java has these at all, but you could always create reusable methods which provides this behaviour. &lt;/div&gt;&lt;div&gt;&lt;br /&gt;&lt;/div&gt;&lt;div&gt;Next time you start to write a foreach loop, have a look to see if what you are really doing is a filter, a map or a fold. You may find you save yourself a few lines of code.&lt;/div&gt;&lt;div&gt;&lt;br /&gt;&lt;/div&gt;&lt;div class="blogger-post-footer"&gt;&lt;img width='1' height='1' src='https://blogger.googleusercontent.com/tracker/5984183628613054769-8265936050440759883?l=sarahtaraporewalla.blogspot.com' alt='' /&gt;&lt;/div&gt;</content><link rel='replies' type='application/atom+xml' href='http://sarahtaraporewalla.blogspot.com/feeds/8265936050440759883/comments/default' title='Post Comments'/><link rel='replies' type='text/html' href='http://www.blogger.com/comment.g?blogID=5984183628613054769&amp;postID=8265936050440759883' title='3 Comments'/><link rel='edit' type='application/atom+xml' href='http://www.blogger.com/feeds/5984183628613054769/posts/default/8265936050440759883'/><link rel='self' type='application/atom+xml' href='http://www.blogger.com/feeds/5984183628613054769/posts/default/8265936050440759883'/><link rel='alternate' type='text/html' href='http://sarahtaraporewalla.blogspot.com/2008/08/lists-filter-map-and-reduce.html' title='Lists: Filter, Map and Reduce'/><author><name>Sarah Taraporewalla</name><uri>http://www.blogger.com/profile/06551171381021637312</uri><email>noreply@blogger.com</email><gd:image rel='http://schemas.google.com/g/2005#thumbnail' width='16' height='16' src='http://img2.blogblog.com/img/b16-rounded.gif'/></author><thr:total>3</thr:total></entry><entry><id>tag:blogger.com,1999:blog-5984183628613054769.post-9109122872431570720</id><published>2008-08-11T22:15:00.000+01:00</published><updated>2008-08-11T22:43:24.980+01:00</updated><title type='text'>Maybe null</title><content type='html'>My colleague &lt;a href="http://andyp-tw.blogspot.com/"&gt;Andy&lt;/a&gt; posted today about &lt;a href="http://andyp-tw.blogspot.com/2008/08/returning-null-considered-dishonest.html"&gt;Returning null considered Dishonest&lt;/a&gt; and while I agree with his sentiments, I disagree with his solution.&lt;div&gt;&lt;br /&gt;&lt;/div&gt;&lt;div&gt;Andy's premise is that you should never expect or return a null object as "&lt;span class="Apple-style-span"  style="font-family:'times new roman';"&gt;&lt;span class="Apple-style-span" style="font-style: italic;"&gt;Returning null is dishonest. It requires others to check that we've upheld our side of the bargain&lt;/span&gt;&lt;/span&gt;".  His solution is to throw meaningful exceptions within the method, so the happy path will return a not-null object, and the unhappy path throws exceptions.&lt;/div&gt;&lt;div&gt;&lt;br /&gt;&lt;/div&gt;&lt;div&gt;This highlights one practice which I get annoyed with when I see it. Programming by exception is never a good idea. Exceptions should be reserved for exceptional circumstances only and should not contain business logic. If there is a possibility that the system can get into a state which returns null, then it should handle that situation, instead of letting it throw a tantrum and yell at the caller. &lt;/div&gt;&lt;div&gt;&lt;br /&gt;&lt;/div&gt;&lt;div&gt;A better alternative would be to return an object which may or may not contain the value required. This Maybe object can have two implementations: when it can return the value, it returns a Something which contains the value;  and when it cannot return the value (ie value would be null) it returns a Nothing (perhaps with a message detailing why).&lt;/div&gt;&lt;div&gt;&lt;br /&gt;&lt;/div&gt;&lt;div&gt;To continue Andy's example of the Vending Machine which dispenses a drink only if enough money has been inserted and there is enough stock, we can take a look at how Maybe objects can be used. &lt;/div&gt;&lt;div&gt;&lt;br /&gt;&lt;pre&gt;public Maybe&lt;drink&gt; giveMeADrink()&lt;br /&gt;{&lt;br /&gt; if (weDontHaveEnoughMoney)&lt;br /&gt; {&lt;br /&gt;  return new Nothing(notEnoughMoneyMessage)&lt;br /&gt; }&lt;br /&gt;&lt;br /&gt; if (weDontHaveEnoughStock)&lt;br /&gt; {&lt;br /&gt;  new Nothing(weDontHaveEnoughStockMessage)&lt;br /&gt; }&lt;br /&gt;&lt;br /&gt; return new Something(new Drink())&lt;br /&gt;}&lt;br /&gt;&lt;br /&gt;// Caller&lt;br /&gt;Maybe[Drink] drink = giveMeADrink()&lt;br /&gt;if (drink.IsPresent)&lt;br /&gt;{&lt;br /&gt; SlideDownChute(drink.Force())&lt;br /&gt;} else {&lt;br /&gt; ReportProblem(drink.Force())&lt;br /&gt;}&lt;/drink&gt;&lt;/pre&gt;&lt;br /&gt;To me its a much cleaner version, you are coding for the situations that can actually occur, and not relying on try-catch statements around the place. &lt;/div&gt;&lt;div&gt;&lt;br /&gt;&lt;/div&gt;&lt;div&gt;My advice? Steer clear of exceptions and return Maybes instead of nulls.&lt;/div&gt;&lt;div&gt;&lt;br /&gt;&lt;/div&gt;&lt;div class="blogger-post-footer"&gt;&lt;img width='1' height='1' src='https://blogger.googleusercontent.com/tracker/5984183628613054769-9109122872431570720?l=sarahtaraporewalla.blogspot.com' alt='' /&gt;&lt;/div&gt;</content><link rel='replies' type='application/atom+xml' href='http://sarahtaraporewalla.blogspot.com/feeds/9109122872431570720/comments/default' title='Post Comments'/><link rel='replies' type='text/html' href='http://www.blogger.com/comment.g?blogID=5984183628613054769&amp;postID=9109122872431570720' title='7 Comments'/><link rel='edit' type='application/atom+xml' href='http://www.blogger.com/feeds/5984183628613054769/posts/default/9109122872431570720'/><link rel='self' type='application/atom+xml' href='http://www.blogger.com/feeds/5984183628613054769/posts/default/9109122872431570720'/><link rel='alternate' type='text/html' href='http://sarahtaraporewalla.blogspot.com/2008/08/maybe-null.html' title='Maybe null'/><author><name>Sarah Taraporewalla</name><uri>http://www.blogger.com/profile/06551171381021637312</uri><email>noreply@blogger.com</email><gd:image rel='http://schemas.google.com/g/2005#thumbnail' width='16' height='16' src='http://img2.blogblog.com/img/b16-rounded.gif'/></author><thr:total>7</thr:total></entry><entry><id>tag:blogger.com,1999:blog-5984183628613054769.post-8329873885757532329</id><published>2008-08-10T07:56:00.001+01:00</published><updated>2008-08-10T19:39:39.506+01:00</updated><title type='text'>JQuery is your friend</title><content type='html'>&lt;div&gt;Lately, I have had the opportunity to add some pretty funky usability behaviour on websites thanks to &lt;a href="http://jquery.com/"&gt;JQuery&lt;/a&gt; and some UI Plugins. &lt;br /&gt;&lt;/div&gt;&lt;div&gt;&lt;br /&gt;&lt;/div&gt;&lt;div&gt;If you haven't used JQuery before - start now. It is really simple to add some really cool behaviour. Need to find all the checkboxes on your page? Then $('input[type="checkbox"]') returns the list of them. Methods are also chained, which can often make long unreadable javascript files more concise, and more verbose at the same time. &lt;/div&gt;&lt;div&gt;&lt;span class="Apple-style-span"   style="color: rgb(172, 211, 115);   line-height: 16px; white-space: pre;font-family:-webkit-monospace;font-size:13px;"&gt;&lt;br /&gt;&lt;/span&gt;&lt;/div&gt;&lt;div&gt;I have played around with &lt;a href="http://docs.jquery.com/UI/Slider"&gt;sliders&lt;/a&gt;, &lt;a href="http://docs.jquery.com/Plugins/Treeview/treeview"&gt;treeviews&lt;/a&gt;, &lt;a href="http://plugins.jquery.com/project/tablesorter"&gt;tablesorting&lt;/a&gt;, &lt;a href="http://docs.jquery.com/UI/Datepicker"&gt;date pickers&lt;/a&gt; and &lt;a href="http://plugins.jquery.com/project/form"&gt;ajax forms&lt;/a&gt; and they have all been a dream to implement. Typically, we would start estimating stories for one of these functions as a Medium, but then as soon as we found and used the plugin, we realised it was actually a Small.&lt;/div&gt;&lt;div&gt;&lt;br /&gt;&lt;/div&gt;&lt;div&gt;Of course, not all plugins are easy to use, especially when looking at cross browser issues. My rule now is if it is not on the JQuery plugin list, then I won't even bother looking at it. I also note who has written it - you will notice that a large number of good plugins come from one or two authors - now, I trust any plugin that they write and will use it if there is one there. My other rule is to spend no more than 10 minutes trying to make it work. If after that time I still haven't got it working (on at least all browsers other than IE) then I look for another plugin, or I roll my own.&lt;/div&gt;&lt;div&gt;&lt;br /&gt;&lt;/div&gt;&lt;div&gt;We have been loving working on the stories which require funky usability controls, so much so that I have introduced a new motto for my current project - jQuery is your friend.&lt;/div&gt;&lt;div&gt;&lt;br /&gt;&lt;/div&gt;&lt;div&gt;It's not all fun and games however - you do need to be disciplined as to when and how to use jQuery, as testing your app may not be so easy with a lot of javascript obfuscation. I have found browser based testing tools like Selenium have problems interacting with the jQuery functions especially when you bind an element to a click or change event. &lt;/div&gt;&lt;div&gt;&lt;br /&gt;&lt;/div&gt;&lt;div&gt;All in all, however, you will find it a dream working with jQuery.&lt;/div&gt;&lt;div class="blogger-post-footer"&gt;&lt;img width='1' height='1' src='https://blogger.googleusercontent.com/tracker/5984183628613054769-8329873885757532329?l=sarahtaraporewalla.blogspot.com' alt='' /&gt;&lt;/div&gt;</content><link rel='replies' type='application/atom+xml' href='http://sarahtaraporewalla.blogspot.com/feeds/8329873885757532329/comments/default' title='Post Comments'/><link rel='replies' type='text/html' href='http://www.blogger.com/comment.g?blogID=5984183628613054769&amp;postID=8329873885757532329' title='1 Comments'/><link rel='edit' type='application/atom+xml' href='http://www.blogger.com/feeds/5984183628613054769/posts/default/8329873885757532329'/><link rel='self' type='application/atom+xml' href='http://www.blogger.com/feeds/5984183628613054769/posts/default/8329873885757532329'/><link rel='alternate' type='text/html' href='http://sarahtaraporewalla.blogspot.com/2008/08/jquery-is-your-friend.html' title='JQuery is your friend'/><author><name>Sarah Taraporewalla</name><uri>http://www.blogger.com/profile/06551171381021637312</uri><email>noreply@blogger.com</email><gd:image rel='http://schemas.google.com/g/2005#thumbnail' width='16' height='16' src='http://img2.blogblog.com/img/b16-rounded.gif'/></author><thr:total>1</thr:total></entry><entry><id>tag:blogger.com,1999:blog-5984183628613054769.post-2805597226637681947</id><published>2008-08-09T18:35:00.000+01:00</published><updated>2008-08-10T12:50:59.597+01:00</updated><title type='text'>Picking the right domain to model</title><content type='html'>&lt;span class="Apple-style-span"  style=" ;font-family:Times;"&gt;&lt;div style="border-top-width: 0px; border-right-width: 0px; border-bottom-width: 0px; border-left-width: 0px; border-style: initial; border-color: initial; margin-top: 0px; margin-right: 0px; margin-bottom: 0px; margin-left: 0px; padding-top: 3px; padding-right: 3px; padding-bottom: 3px; padding-left: 3px; width: auto; font: normal normal normal 100%/normal Georgia, serif; text-align: left; "&gt;When designing your code, it is important to model the business domain. However, how do you know you have modeled the right domain? Sometimes you need to look beyond the domain objects, and see what you are actually implementing.&lt;div&gt;&lt;br /&gt;&lt;/div&gt;&lt;div&gt;On my latest project, we started modeling what we thought were the correct business objects. Essentially, the project was to build online booking registration. The registration spans many pages (sections), has no session state (see &lt;a href="http://dan.bodar.com/2007/10/06/3/"&gt;Dan Bodart's blog &lt;/a&gt;under heading No Session State just persistent documents) and has a similar usability concept as described in &lt;a href="http://www.dancingmango.com/blog/2008/02/12/real-world-forms/"&gt;Marc McNeill's blog&lt;/a&gt;.&lt;/div&gt;&lt;div&gt;&lt;br /&gt;&lt;/div&gt;&lt;div&gt;Initially our model had discreet objects, and their complex relationship between them. We soon realised that what we should be representing was not these domain objects but actually the form itself.&lt;/div&gt;&lt;div&gt;&lt;br /&gt;&lt;/div&gt;&lt;div&gt;So, we turned our model on its head and modeled the form instead. Now, the form consists of a list of sections on the form, and each section consists of a list of fields in the section. A field consists of a label, the value (which the user entered - represented as a string), validators (if this field have a value when submitting the form, or if the value has special qualities like a number between 100 and 1000) and converters (to transform the value from a string to the necessary type like integer). Representing it in this manner has the added benefit that we retain the user entered content, even if it was not of the right type. &lt;/div&gt;&lt;div&gt;&lt;br /&gt;&lt;/div&gt;&lt;div&gt;We have been using this form based approach for a few months now, and I am sure it has really helped our progress. A new feature was requested the other day - the ability to turn off sections under certain circumstances. This has been quite easy to build with the form model; I don't know how much extra work it would be in the old design, but I'm sure a lot more complex.&lt;/div&gt;&lt;div&gt;&lt;br /&gt;&lt;/div&gt;&lt;div&gt;What has this taught me? Don't just look at the forest - the tree may prove to be better after all.&lt;/div&gt;&lt;/div&gt;&lt;/span&gt;&lt;div class="blogger-post-footer"&gt;&lt;img width='1' height='1' src='https://blogger.googleusercontent.com/tracker/5984183628613054769-2805597226637681947?l=sarahtaraporewalla.blogspot.com' alt='' /&gt;&lt;/div&gt;</content><link rel='replies' type='application/atom+xml' href='http://sarahtaraporewalla.blogspot.com/feeds/2805597226637681947/comments/default' title='Post Comments'/><link rel='replies' type='text/html' href='http://www.blogger.com/comment.g?blogID=5984183628613054769&amp;postID=2805597226637681947' title='0 Comments'/><link rel='edit' type='application/atom+xml' href='http://www.blogger.com/feeds/5984183628613054769/posts/default/2805597226637681947'/><link rel='self' type='application/atom+xml' href='http://www.blogger.com/feeds/5984183628613054769/posts/default/2805597226637681947'/><link rel='alternate' type='text/html' href='http://sarahtaraporewalla.blogspot.com/2008/08/picking-right-domain-to-model.html' title='Picking the right domain to model'/><author><name>Sarah Taraporewalla</name><uri>http://www.blogger.com/profile/06551171381021637312</uri><email>noreply@blogger.com</email><gd:image rel='http://schemas.google.com/g/2005#thumbnail' width='16' height='16' src='http://img2.blogblog.com/img/b16-rounded.gif'/></author><thr:total>0</thr:total></entry></feed>
