Subscribe
Sign In
|
 Wednesday, October 01, 2008
Is TDD over the top? Surely can I write my tests 'alongside' my code? Short answer: No. Long answer: To borrow Michael Feathers, author of "Working effectively with Legacy Code" the definition of legacy code is code without tests. By writing a function without a test first, you've just banged out a whole bunch of legacy code. It might not feel like it, but you could have just wasted your precious time. OK, so lets pretend we have some of this legacy code in front of us. We begin writing some tests to cover it. What you'll find is that many programmers do one of a few things: - Coder A will write four or five tests for every method and generally not have to change their implementation much, if at all.
- Coder B writes less tests overall, but in order to get it there they had to change their code due to recognising some unnecessary coupling or logic.
The next few examples are people who would have used TDD or no tests at all... - Coder C used TDD but strangely the end result looks like Coder A's code.
- Coder D thinks unit testing is a waste of time, and has already deployed to production by now and is currently smugly sipping on Kool Aid.
- Coder E only wrote a few tests, each test concerned with what the code should do, not what the code currently does, or how it goes about doing it.
Now that we have brutally put everybody in a box with rash generalizations and assumptions, lets come up with a way to throw a cat amongst the pigeons. Generally the best way to do this to a developer, is to ask them to add a new feature to their code. - Coder A when finished, finds that all the old tests wont even compile let alone pass because the new requirements severely altered the required architecture. Time is wasted rewriting all the tests to facilitate the new architectural requirements.
- Coder B finds that only half of the old tests build or pass after implementing the new code. Because they removed some coupling it was easy enough to add, but they wasted time on some old tests that were obsolesced by the new architecture.
- Coder C decides that the existing test suite isn't going to facilitate the new requirements. After they rewrite most of their tests they rewrite the code to satisfy them. Its like much Coder A's experience just in reverse.
- Coder D deploys the new code to production or QA, only to find that the new changes stomped all over old functionality. What do you mean it 'doesn't work'? That's impossible! Time for a week long debugging session.
- Coder E on the other hand writes one more test to the test suite and adds as little code as necessary to make it pass, then brutally refactors anything possible. None of the tests needed rewriting in the process. All user requirements are met and the project is delivered on time and on budget. If your lucky that is...
What some people fail to understand, is that using TDD doesn't prevent you from writing bad code. On the contrary, it can encourage you to over specify things. When you over specify, you increase the places in your test suite that depend on how your implementation is structured. The very same thing happens when you write a function, and then a test or write tests 'alongside' your code. This is the mistake that Coder C makes, taking the bull by the tail, instead of the horns. Coder E has no idea that he/she is in part practicing BDD. Its a natural progression from blindly banging out tests to cover every feasible outcome. Eventually you get a feel for tests that give you maximum 'bang for buck'. These tests provide maximum (quality) coverage for the least effort. In other words, we aren't bothering with a test per function. We are writing one test per desired behaviour. OK so every now and again, you head down the wrong track and tear up a few behavioural tests. Usually that's because you misunderstood the requirements, not how to code it, and that's where the value lies. If you cant write a behavioural test, then you haven't understood the problem fully. If you don't understand the users problem, why are you coding? That's why initially, its tempting to TDD blindly, you can ignore certain aspects of the users problem and just simply code until you think you got it right. Of course there are a few other aspects to BDD that I'm sure you're either aware of, or hopefully discover after reading this, but its important to remember: BDD isn't something new and funky fresh. Its not the latest soda pop fad. At its heart its simply TDD Done Well.
 Monday, September 29, 2008
In my previous post I espoused my latest love affair for Stackoverflow. I still think its an awesome site, however I recently got stung by the ever present reality that there are some people who think its for programming questions only, and others who think its for all questions, as long as they relate to programming. I asked this question. Sure its subjective, sure it can involve answers that apply to life in general. I even knew that it might yield answers that were opinions rather than fact. However, its firmly under the banner of questions that can be answered. Your answer might work for you and not for me, but that doesn't mean we haven't answered the question, it means the question has more than one answer. Much like the difference between a maze and a labyrinth. I'm of the opinion that this site was created to provide value to its members. Clearly the response to the question indicates that many members found it to be a useful one. Unfortunately I'm at the mercy of editors who may or may not have a clear grasp of Venn Diagrams. I was told that my question is not about programming because its answers can be applied to any profession. "This is nothing to do with programming - it applies to all working people" Given the above diagram we can posit that a question that applies to all professions also applies to the profession of programming. Especially since I'm a programmer asking other programmers! In another comment, emphasis mine: "It's like asking how to make a peanut butter and jelly sandwich suitable for eating while coding - just because it's valuable to many programmers does not make it a programming question." I'm concerned that semantics is more important to the commenter than good content when I see this. If peanut butter and jam sandwich recipes were truly useful to many programmers then why would we want to stop people from using the site to discuss it? If its useful, its a tool like any other. Discussing techniques to combat lack of motivation are as important as techniques to combat code coupling. Furthermore, in light of the fact that the site creators clearly condone this question I'd say that the FAQ was deliberately using soft terminology when guiding the end user what not to ask: "Avoid asking questions that are subjective, argumentative, or require extended discussion." Blind adherence to the literal meaning to such a mantra is what gives us such wonderful things as fundamentalism. The spirit of what is going on behind such a sentence is to prevent questions like "Which is better, C# or VB?", not potentially useful discussion. The key here is that if you choose to take the FAQ literally then you should also take this literally: As long as your question is: - detailed and specific
- written clearly and simply
- of interest to at least one other programmer somewhere
... it is welcome here. I realize that there is a worry about Signal to Noise ratio, but the site is tagged and searchable for heavens sake. Presumably in future releases we'll have the ability to filter out tags in your search results at whim and will anyway. The fact remains, subjective questions are some of the most popular on the site. Some see this as a scourge that needs to excommunicated. Personally I think it demonstrates that programmers on the whole : a) Like to have a bit of fun from time to time, b) Recognize that there is more to programming than code. All of this is moot however, given that those people who think that all time management solutions in the profession of personal training necessarily applies to that of a surgeon and therefore programmers are clearly wrong. Let me demonstrate with a small sample of the sorts of differences we are likely to find across two different professions: Q: When is it a good time to stop coding? A: Whenever you feel tired and unmotivated. Get up and walk around, maybe get some exercise and get the blood flowing. Now lets apply this to the profession of say, soldiering: Q: When is it a good time to stop shooting at the enemy? I think its clear that ceasing to fire upon the enemy and then getting up and having a walk around when you are simply tired and unmotivated, could result in the untimely cessation of your career as a soldier. I'm keen to hear others thoughts on the matter.
 Tuesday, September 23, 2008
So I found a new addiction last night. I decided to check out http://stackoverflow.com last night for the first time. Yes I know I'm late to the party, but since I love to share....I will :D What hooked me was three things that were really easy to achieve: 1) Registering and logging in. 2) Navigating and finding interesting and relevant information. 3) Helping others else out with answers to their questions. I haven't actually asked a question yet, although from what I've seen that's just as good as the rest of it. Another thing that leaves me in awe is that nobody has done this as good as stack overflow before. Q&A websites aren't a new thing. But Jeff Atwood, Joel Spolsky et al. simply took an old format and brought some new innovations to it, as well as spending some real effort in the finer details. For those of you as yet unaware of stack overflow, the primary driving force is a score based incentive system that encourages users to contribute and to contribute appropriately. The more appropriately you contribute, the higher the level of privilege you gain. You can essentially earn your moderator status without permission from err...other moderators. Even if you don't necessarily provide the best answer, the scoring system allows other people in the community to call out the bad answers and provide better answers. Once you've earned yourself a good enough score (reputation) you can also mark down answers you feel to be erroneous. Anyway I've harped on about how it works for long enough....visit the site and check it out for yourself. This new(ish) website is a great example of somebody or a group of people just getting in there and doing something and doing it better. Rather than trying to dream up the next killer app, they took a generic idea and absolutely nailed it like its never been nailed before. I know I am going to learn a lot from this place, and I'm very excited to have new means to directly help others in my community from the comfort of my lounge room.
 Thursday, September 18, 2008
I often start personal coding projects on a weekend because I am passionate about programming. I wouldn't be here if I wasn't. The problem is that those projects don't get finished very often. The sorts of projects I do find myself finishing are the ones when I've been truly interested in the problem domain. This isn't a ground breaking revelation. I just have to remind myself of this every now and again. My problem is not that I need to develop with passion, rather I should attempt to develop for things I am passionate about. Being passionate about programming gives me a special benefit: I can come up with useful ideas for other programmers and implement them. Unfortunately coming up with cool ideas for programming usually ends in finding somebody else is already halfway through implementing it. Time to revisit my alt.pursuits for inspiration.
 Tuesday, September 09, 2008
I know its minor and easily fixed but I have to say that I really hate this about 3rd party installations to Visual Studio. I get quite used to certain keyboard shortcuts for every day tasks and the last thing I need is my F12 key hijacked. Some products are great about this aspect of tool development, some aren't. What I didn't expect was the recent F# CTP to do it to me. In fairness, it is still essentially in beta. One of the great Visual Studio features of late has surely been smart tags in code, which can be expanded using Ctrl+. or the abominable Shift+Alt+F10: So, if you too are fond of using the Ctrl+. combo in Visual Studio to expand smart tags to do things quickly like include references, insert using statements and correct syntax errors and you want the latest F# goodies then for the time being you'll need to re-map the key combo. Or you could use the alternative wrist bender Shift+Alt+F10, and for me that was not an option. To do this, open the Options dialogue from the Tools menu in Visual Studio. Browse to the Keyboard options under the Environment heading and re-map the View.ShowSmartTag command. I've written to F# feedback to let them know about this minor issue. ***UPDATE*** Luke Hoban from F# Bug reports confirms this workaround and assures me that this will be included in a soon to be released list of known issues. Thanks Luke!
Just a quick post to highlight the recent release of the F# compiler for Visual Studio. This release shows some real improvement upon the IDE integration featuring true F# project files and an improved language service which benefits both intellisense and background compilation. I didn't realise how much I liked Visual Studio projects until I was deprived of their functionality. Just simply having a project file that operates like C# or VB projects is a real boon to F# newbies and experts alike. My previous experiences with intellisense in F# were such that I would often ignore it as it was easily confused. This appears to be less of a problem now and is much more of a help than a hindrance. So if you haven't already, download and install the F# September CTP from the MS download centre and have a look.
 Wednesday, August 27, 2008
While reading Chuck's excellent post on the value of both knowing your problem domain before tackling your problem and checking in often, I found myself nodding profusely. I love it... he states: Write tests first! Do it! DO IT NOW. I'd like to add: NOW CHECK IN!! I wish I could...often my problem is *when* to check in. I know I have to do it often, but when? After I finish a task? What if that is a few days away? What is a reasonable amount of time? When I say task I am referring to a TFS work item. Since we are a scrum shop now it is actually a sprint backlog item. I have TDD at my side, and we have CI builds at work. Why not check in after every passing test cycle? To be honest, checking in after every passing test feels like I'm wasting more time doing the check in dance, than I am saving time. Having said that, it appears that this is a widely accepted approach. Martin Fowler suggests otherwise. It appears he is task oriented when it comes to checking in: Now I take my working copy and do whatever I need to do to complete my task. This will consist of both altering the production code, and also adding or changing automated tests. ... With a good build, I can then think about committing my changes into the repository. I think it feels more natural that way. Its like a 'reward' for finishing a task. The feedback loop advantage of TDD isn't hindered by the longer feedback time of a CI build so much. However, I'm often left with sprint backlog items whose scope might mean that I'm programming for days on end. This is the root of check in evil for me. If a work item is so broad that it will take days to complete, then the impetus to check in is diminished such that I can get so wrapped up in the detail of the problem that I will forget to check in. And that's my fault. I'd love to blame it on the process but I can't. Sure the analysis of the product backlog item could have been more thorough, but we don't want to get too far into implementation details at that point or else we waste the whole teams time. I should have the sense upon undertaking a task that has been written up as "Import old Foo data for Foo version 2", to split it up in to its discreet units of work. There are SQL tables to write create scripts for. There is a transformation layer to design and implement. There is deployment to think about. Acceptance testing. So on and so forth. It is *my job* to define the goals on the road to task completion. So I come full circle and refer back to Chuck's post and the idea that we should think about what we are going to do before we go and do it. Coding from hip make pain for coder </grunt> Accept a task and analyse the problem domain. Divide it up into check in sized work items. Eat. Repeat.
 Friday, August 22, 2008
I've always loved vi and vim with a passion, and when after reading a post from JP Boodoo about ViEmu I felt compelled to give it a whirl. ViEmu integrates vi/vim functionality with Visual Studio. Yes.... you too can :wq code files. Initially, I was concerned that it would hinder rather than help, mainly due to a discordance between the editing paradigms of vi and Visual Studio. Vi uses discreet editing, navigation and selection modes to maximise the usefulness of the keyboard in light of traditional console based terminals. With advent of the graphical text editor, this paradigm fell from favour as keyboard usage was gradually overtaken by ever increasing armies of icons and other visual metaphors. In spite of this, coders generally pride themselves as 'shortcut-smiths' and I found that my vi skillset was proving useful even with Visual Studio. I should also point out that at home I run Resharper and at work I use Refactor Pro and CodeRush, and that Viemu for the most part appears to play very nicely alongside them. ViEmu also works from Word, Outlook and SQL Management Studio. So what more could I possibly get out of Visual Studio using a tool like viemu? I'd like to share some of the things I like the most about Viemu. Navigation In short, and without giving a course on vi usage, we can move around a and edit code files in ways that other editors don't even bother with. The following is a small sample of the possibilities. - Want to move 10 lines down from your current position? 10j
- 5 words to the left? 5w
- End of a word? e
- Next line of whitespace? }
- Move up to the closing parenthesis? %
- Now move to the matching opening parenthesis? % again
- Move to the 5th instance of the , character? 5f,
Editing - Delete the next 10 lines? d10d
- Change the next 5 words? c5w
- Append to the end of the current word? a
- Append to the end of the line? A
- Delete everything up to the closing parenthesis (a personal fave)? d%
- Change the text upto and including the 3rd ) character? c3f)
I'm often confronted with the comment "But who deletes 10 lines of code?" Well, for starters, I work with line numbering ON. Let's say I don't want 3 methods anymore. I look at my current line position, I look at the line the last method ends on. I subtract the two values in my head, that comes to 43 lines. I then type d43d and I'm done. The point is, that you begin to notice patterns in code. Assignments are usually at least three words long. A method with no parameters in C# takes 3 words to move to the opening bracket. Hitting %% gets me to the same place in that case also. Having the ability to add numbering and repetition to navigational and editing tasks is very powerful, and now I'll show you just one of the myriad way you can harness it. Vi Macros Once you have familiarized yourself with the toolset, it becomes quite easy to record macros for repetitive tasks. We use SQL scripts to deploy test data at work and every now and again I'll hear the repetitive tap-tap-tap of somebody hitting the following sequence of keys: END, CTRL+V, DOWN ARROW over and over and over again. Here is an example: PRINT 'Employees.'
INSERT INTO dbo.Employees
(EmployeeNumber, EntityGuid, DomainLogin)
SELECT 'EM001', '018B163B-7D4F-49E1-A640-6BD9B65073FF', 'DOMAIN\EM001'
UNION SELECT 'EM002', '3D3201F8-523D-43B1-89BC-F2FF8CAEBD56', 'DOMAIN\EM002'
UNION SELECT 'EM003', '48EC5825-374F-4043-849D-308B2C8AA093', 'DOMAIN\EM003'
--repeat 50 more times
GO
The usual goal might be that a role column was added, and for starters we want to assign each employee to the same role. First we go to the insert line and add the Role column at the end. Now to begin the macro that will do the heavy lifting.
First I enter normal mode by hitting escape or ctrl+[. Next I type qa to start recording a macro to register 'a'. I then type A to append to the end of the line. I'm now in insert mode, so I type , 'Users'. I exit insert mode with escape or ctrl+[ and then move to the next line with j. Finally, to finish the macro I hit q.
To recap, all I typed was: <esc>qaA,'Users'<esc>jq Thats a whopping 15 keystrokes including the string I had to write anyway.
I now have a macro I can reuse by simply using the recall macro command @. To recall macro 'a' I actually have to type @a.
'So what', you say, 'That only does it once and having to type @a over and over again is just as tedious as paste, end, down??'
Well the final trick is that to do it 52 times over I type 52@a. Repetition of commands is definitely one of vi's strengths and you can use it pretty much everywhere.
Variation: I want the the Role column to be the 3rd column in my insert. Simple.. a few minor changes like instead of using A I would use ^2f, to move to the second comma. I would have to write: <esc>qa^2f,i'Users', <esc>jq then finally 52@a and I'm done.
I'll admit, there is a bit of thinking going on there, and I might not be typing at 80 wpm, but I'm saving myself a whole lot of RSI. Oh... and looking totally l33t when I run that macro 52 times.
So is it worth it?
Well, I think so, but I think it really depends on the type of person you are. If you've already fallen for vi, and Visual Studio seems only bearable with Resharper installed, then I'd say absolutely get Viemu. It doesn't cost much and you can utilize almost everything vim has to offer. If not, the learning curve isn't huge, but its significant. Thankfully, Viemu maps Ctrl+shift+alt+V to instantly turn it on or off, so if it starts hurting your head, you can escape the pain. It plays nicely with existing productivity tools, and caches any keyboard mappings that it steals during operation, and it will put them back if you switch it off.
Still, vi is a cryptic way of editing code, so if you struggle with remembering the keyboard shortcuts for Build, Step Into & Step Over, then I'd suggest that this product isn't for you. But if you want to add a new light sabre to your existing Jedi toolkit, then I'd encourage you to give it a try. Maybe even install gvim for a while to replace notepad, to help get used the whole vi thing.
 Wednesday, June 11, 2008
Today Resharper 4.0 goes RTM, if you haven't been following the EAP, you might be interested to know that we now have full C# 3.0 language and LINQ support. That's not all we get, there are a swag of cool new refactorings, solution wide code analysis, extra framework annotations, camel humps in code completion....the list just goes on. There are some improvements to the VB experience like new refactorings only previously supported in C# 2.0: Convert Method to Property Convert Property to Method Pull Members Up Push Members Down Extract Interface Extract Superclass Convert Interface to Abstract Class Convert Abstract Class to Interface Extract Class from Parameters Use Base Type Where Possible Replace Constructor with Factory Method The ASP.NET guys don't miss out either, amongst other things - a performance increase to page analysis, which has been a real problem for large ASP.NET pages in the past. Personally, I find Resharper to be the best C# productivity tool out there for the money, and they are paying more and more attention to VB.NET. Combined with Viemu its my productivity suite of choice and I encourage you to give them both a try.
 Wednesday, May 14, 2008
Recently I discovered the xUnit.NET framework for unit testing, and it is a very nice minimalist framework for TDD. I especially like writing tests for F# code using it. It allows me to write very short test suites against any CLR library, in most .NET languages. For example:
#light
open Xunit open NT.Model
let sut = new Person("Jim")
[<Fact>] let jim_is_a_geek() = Assert.True(sut.IsAGeek)
The Person class could be written in C# or VB and used here. Also note that the ultimate class name of this test is inferred by the filename. I could add explicit module and namespace information if necessary.
In something like MbUnit / NUnit / Gallio I have to use the following OO style syntax...
#light
namespace NT.Model.Specs
module PersonSpecs
open MbUnit
open NT.Model
[<TestFixture>]
type jims_behaviours() =
let sut = new Person("Jim")
[<Test>]
member j.is_a_geek() = Assert.True(sut.IsAGeek)
Note that the namespace and module must be declared in order for the gallio runner to discover the tests. I think this might be a bug...
However, regardless of the framework you use, F# also lends itself well to setting up for customized approaches to testing. I feel this has some potential for BDD testing in F#. Take the following example:
#light
open Xunit
let MustEqual expected actual = Assert.Equal(expected, actual)
[<Fact>]let a_fluent_assertion() = 0 |> MustEqual 0
Taking this one step further we can take advantage of operator overloading to provide extremely terse tests. Note that I don't actually advocate doing this, only pointing out that its possible:
#light
open Xunit
let (&=) expected actual = Assert.Equal(expected, actual)
let (&!=) notExpected actual = Assert.NotEqual(notExpected, actual)
[<Fact>]
let an_obscure_assertion() = 0 &!= 1
Based on these samples, I think it is clear that without much effort, a fluent specification interface could be arrived at, perhaps even a domain specific one at that.
F# record types are readily testable also:
#light
open Xunit
type Person = { name : string; age : int; }
let Jim = { name="Jim"; age=28 } let Fred = { name="Fred"; age=52 }
let IsNot expected actual = Assert.NotEqual(expected, actual)
[<Fact>] let jim_is_not_fred() = Jim |> IsNot Fred
Sometimes, the assertion framework isn't needed, but having a test runner is still obviously handy. For the next example I setup a discriminated union and then use pattern matching to determine the outcome of the test simply using the built in failwith keyword:
#light
open Xunit
type Animal =
| Dog
| Cat
type Person =
{ name : string;
age : int;
pet : Animal; }
let Jim = { name="Jim"; age=28; pet=Cat; }
[<Fact>]
let Jim_cannot_own_cats() =
match Jim.pet with
| Cat -> failwith("Jim owns a cat!")
| _ -> ()
A snippet from the xUnit console runner output for this failing test: Tests failed:
1) Jims_specifications.jim_cannot_own_cats : Microsoft.FSharp.Core.FailureException : Jim owns a cat!
On that...hopefully soon tools like Gallio will provide us with some F# support in Visual Studio for the Resharper test runner or even MSTest. At current support for xUnit testing with Gallio in F# projects appears to be a non starter. Alternatively, latest SharpDevelop betas have inbuilt F# and NUnit support which I find to be quite good.
In the meantime we can go all 'old school' on VS 2008 to provide some ease of use.
In the following screen shot I've added the xUnit.NET console runner to external tools by selecting from the menu, Tools, External Tools...
Next I like to map this to a keyboard chord, say Ctrl+R,Ctrl+X:
So that now after building, I can run my entire test suite using my keyboard shortcut to yield a testing experience that is 'good enough' for TDD/BDD development in F#, well, that's my opinion of course :)

 Monday, April 28, 2008
...Other Project Euler posts...
Today, my mission is to solve Project Euler Question #2:
Find the sum of all the even-valued terms in the fibonacci sequence which do not exceed four million.
The obvious solution is to use a brute force approach:
public static int Problem2() { var fib = 0; var sum = 0;
for (var n = 0; fib < 4000000; n++) { fib = Fibonacci(n); if (fib % 2 == 0) sum += fib; }
return sum; }
private static int Fibonacci(int n) { return n < 2 ? 1 : Fibonacci(n - 2) + Fibonacci(n - 1); }
Lazy evaluation
Slightly more elegant solutions do exist. For starters, F# allows us to use lazy evaluation to create sequences of values. This has the advantage of sequence values only being evaluated when necessary. Robert Pickering's "Foundations of F#" gives us the following example for generating fibonacci numbers using lazy evaluation. In fact, the example here is one of an infinite list.
#light let fibs = (1, 1) |> Seq.unfold(fun (n0, n1) -> Some(n0, (n1, n0 + n1)))
Initially, a pair of values (named a tuple) 1 and 1 is piped through to the Seq.unfold function. The unfold function allows us to define how we want our list to be generated. It returns a disciminated union type called Option which in this case is called with a tuple, the first value in the tuple being the value applied to the list, the second value is the accumulator. The accumulator basically allows you to pass some state into next round of calculations. Option types are there own blog post, as they are a totally awesome example of applied discriminated unions.
To put the fibs function into english: fibs takes a tuple of integers (n0, n1), and always returns the first member in the tuple, however when we evaluate the next item in the sequence, the first member of the tuple will be n1 and the second will be n0 + n1. This will go on and on even once we hit the 32bit limit and starting looking at negative integers.
Pattern matching
So how does this help us to solve question two? Using a similar approach as the C# version we could alter the way the list is generated before we summate:
#light
let summate x = x |> Seq.sumByInt (fun n -> n) let Question2 = (1, 1) |> Seq.unfold(fun (n0, n1) -> match n0 with | n0 when n0 % 2 = 0 -> Some(n0, (n1, n0 + n1)) | n0 when n0 > 4000000 -> None | _ -> Some(0, (n1, n0 + n1))) |> summate
Here, I'm using simple pattern matching to do two things, make sure any numbers that arent even are mapped to 0, and also to ensure that once n0 exceeeds 4 million, we stop generating values in the list. This is the power of the unfold function at play: the ability to lazily evaluate the members of the list and also to define the condition to terminate the list.
A Mathematical approach
However, this is still a brute force approach, although dressed up a little. Since the fibonacci set is full of patterns and properties surely we can take advantage of one or three? Of course, each 3rd term in the fibonacci set happens to be even. We also have an approximate ratio between two consequetive terms: Phi. Therefore, the ratio between even terms is approximately Phi to the power of 3. Using these properties we should be able to come up with the same answer as our brute force approach:
#light let summate x = x |> Seq.sumByFloat (fun n -> n) let PhiCubed = ((sqrt(5.0) + 1.0) / 2.0) ** 3.0 let Question2 = 2.0 |> Seq.unfold (fun x -> match x with | x when x < 4000000.0 -> Some(x, Math.Round(x * PhiCubed)) | _ -> None) |> summate
So with a starting point of 2.0 I simply round the result of x * (Phi ^ 3) to yield each value in my list which is then summed. The C# interpretation as follows:
public static double Problem2() { return EvenFibsBelowFourMillion().Sum(); } private static IEnumerable<double> EvenFibsBelowFourMillion() { var phiCubed = Math.Pow(((Math.Sqrt(5D) + 1D) / 2D), 3); var fib = 2D; do { yield return fib; fib = Math.Round(fib * phiCubed); } while (fib < 4000000); }
In Summary
C# still outperforms F# ever so slightly on my machine, C# taking an average 0.002 milliseconds, F# taking an average 0.003 milliseconds. So far I feel that F# lives up to the promise of a 'similar performance profile as C#'. I'm starting to appreciate the 'point and shoot' nature of F# syntax. Having said that, the C# solution is equally nice and easy to read. I cant wait to get into some of the meatier questions.
 Sunday, April 06, 2008
One of the languages I have decided to learn this year is F Sharp. F# is a multi paradigm programming language; it is capable of expressing ideas in an imperative, functional and object oriented fashion. It is the result of some very hard work by Microsoft Research and integrates into VS2005 and 2008. F# rounds out the MS language ecosystem quite nicely i think, as it provides a solid platform for mathematical solutions, as well as maintaining the ability to be used to create windows applications of all types.
I decided to get my head around using it by reading Foundations in F# and by undertaking Project Euler, a series of mathematical puzzles. I'm certainly not alone, and to set myself apart from those who have trod before me, I've decided to compare the solutions in F# to possible solutions in to my favourite language: C# 3.0. Since I am no maths expert, this could be a real trainwreck...
Question 1: Find the sum of all the multiples of 3 or 5 below 1000.
Sounds simple enough. We can use mod 3 and mod 5 to filter a list of positive numbers below 1000 and sum the result. One approach might be:
static int Problem1() { return MultiplesOfThreeAndFiveBelow(1000).Sum(); }
static IEnumerable<int> MultiplesOfThreeAndFiveBelow(int n) { for (var i = 0; i < n; i++) { if (i % 3 == 0 || i % 5 == 0) yield return i; } }
OK, so thats a little expensive, I've used a generic list instead of an array, but hey it works. Its main strength is that its readable. So how about a functional approach?
let solution = Array.init 1000 (fun x -> if x % 3 = 0 || x % 5 = 0 then x else 0 ) |> Array.fold_left (+) 0
Array.fold_left is a higher order function, since it accepts a function as a parameter. I am passing it the addition operator (a function in its own right) and an accumulator initialized to 0. The first iteration of the fold function will take the value of first element of the sequence and add it to zero. The result is then added to the value of the next element in the sequence to produce a new result and so on. Essentially, it provides the summation required to complete this problem. The downside with this approach is that it naively overestimates the size of the array required, and folding left doesnt immediately lead the reader to think of summation.
I can do better though, F# provides us some constructs for more efficient array initialisations; a comprehension syntax:
let solution = Array.fold1_left (+) [| for x in 1 .. 999 when x % 3 = 0 || x % 5 = 0 -> x |]
While this is readable, some might complain that Array.fold1_left is a cryptic way to summate, and is therefore hard to maintain, so without much effort we can curry it to look like this:
let summate a = Array.fold1_left (+) a let solution = summate [| for x in 1 .. 999 when x % 3 = 0 || x % 5 = 0 -> x |]
I've split the array initialization over 4 lines for extra readability but in essence its only 1-2 lines of readable code to solve Project Euler Problem 1 using F#.
So, for those of you interested in speed, using the time honored technique of taking the average execution time over 1 million executions, the C# implementation came in at around 10 times faster than the final F# one. The first F# implementation was faster but was still two times slower than C#. The main bottleneck seemed to be the array initialization; using the comprehension syntax is a little pricey. But, who cares about optimization anyway? It was only the difference between fractions of a millisecond anyhow :)
 Friday, March 14, 2008
Hey y'all, long time no see. Life has thrown me a few curve balls which impeded my blogability, but rather than boring you with details lets just get into straight into it.
Recently I've had a few queries regarding a check in policy I eluded to in this post. Today I hope to clarify how one might go about implementing a check in policy which ensures that Option Strict is turned on for VB projects.
Rather than rehashing a perfectly good walk through, I suggest you read this article from MSDN to get the basics of Check In Policy creation.
Once we have our check in policy project and have derived a class from Microsoft.TeamFoundation.VersionControl.Client.PolicyBase it is time to start overriding the behaviour of the base rule. Imports Microsoft.TeamFoundation.VersionControl.Client
<Serializable()> _
Public Class OptionStrictPolicy
Inherits PolicyBase
Once we are over that little hurdle we want to:
* Get the set of pending changes that have been selected by the user to check in
* For each pending change determine the project file that the change belongs to
* For each VB project determine if Option Strict has been turned on
* For each project that hasn't got option strict turned on, create a policy warning.
For extra fun I'll do this all with VS2008 & VB9. I love my C# but to be honest VB9 kicks its ass when dealing with XML.
1: Get the set of pending changes that have been selected by the user to check in
Everything from here on out extends the Evaluate method of PolicyBase. Getting the set pending changes selected by the user is a cinch. I've filtered by vb code files, but you could just as easily go for more file types. Public Overrides Function Evaluate() As PolicyFailure()
Dim pendingChanges = PendingCheckin.PendingChanges.CheckedPendingChanges
Dim vbCodeFiles = _
From c In pendingChanges _
Let extension = Path.GetExtension(c.FileName) _
Where extension = _VBFileExtension OrElse extension = _VBProjectFileExtension _
Select c.LocalOrServerFolder, c.FileName
2: For each pending change determine the project file that the change belongs to
This step is a little trickier and basically involves drilling up the folder structure until we find a project file, and then checking the project file for a compilation reference to the pending change. This seems like a good place to refactor into a recursive function...
*SIDE NOTE* Am thinking of starting a petition to all relevant Dictionary makers to make the word "Refactor" a real word. Whose with me?
I'm sure we are all capable of looking for .vbproj files recursively up the folder chain. However we do need to allow for the possibility that there may be two vbproj files in a folder and if so, is our pending change referenced by either of them? To do this I need to go through the project file looking for <Compile> tags that include my pending change. For example in C# we might do it like this var doc = XDocument.Load(XmlReader.Create(projectFilename));
var compileItems = from e in doc.Descendants()
where e.Name.LocalName == "Compile"
select e;
return (from c in compileItems
where c.Attribute("Include") != null && c.Attribute("Include").Value.Contains(filename)
select c).Any();
But since Im using VB today I can do it like this...
Dim doc = XDocument.Load(XmlReader.Create(projectFilename))
Return doc...<Compile>.@Include.Contains(filename)
Not bad...but for this to work I do need to import the namespace of the project file schema, since the syntax that allows for <Compile> is checking qualified names, not local names. Imports <xmlns="http://schemas.microsoft.com/developer/msbuild/2003">
3: For each VB project determine if Option Strict has been turned on
Once I have a list of projects that are loosely associated with a check in, I can easily check for the existence of OptionStrict tags in the vbproj file. OptionStrict still defaults to off, so a lack of OptionStrict tags implies the setting is OFF. However it is perfectly valid to have an OptionStrict tag that is set to OFF so I need to account for those. Private Shared Function IsOptionStrictOn(ByVal project As XDocument) As Boolean
Return project...<OptionStrict>.Value = "On"
End Function
4. For each project that hasn't got option strict turned on, create a policy warning.
Creating policy warnings is a breeze and you can return as many as you want, in this scenario I want to ensure that one is created for each project that is in violation of my rule. The final Evaluate function looks like this... Public Overrides Function Evaluate() As Microsoft.TeamFoundation.VersionControl.Client.PolicyFailure()
Dim pendingChanges = PendingCheckin.PendingChanges.CheckedPendingChanges
Dim vbCodeFiles = From c In pendingChanges _
Let extension = Path.GetExtension(c.FileName) _
Where extension = _VBFileExtension OrElse extension = _VBProjectFileExtension _
Select c.LocalOrServerFolder, c.FileName
Dim vbProjects = From c In vbCodeFiles _
Select GetProjectFile(c.LocalOrServerFolder, c.FileName)
Dim strictOffprojects = From p In vbProjects _
Where Not IsOptionStrictOn(p)
Dim policyFailures = New List(Of PolicyFailure)
Dim messageFormat = "Please turn option strict on in the project file: {0}"
For Each s In strictOffprojects.Distinct
policyFailures.Add( |