February 25, 2008
@ 08:51 PM

There is a discussion in the alt.net mailing list cloud about Cruise Control vs. Team City. I am really happy with CI Factory (a tool that is kind of built on Cruise Control.NET, among other things) and wanted to share an experience I had recently as an example of how it is useful to me.

Our company has a policy that all deployments need to have a specific folder structure, an MSI, a rollout instruction document, a rollback folder for rollback database scripts, a zip of config file changes in a specific directory structure in the zip, blah, blah, blah. We have to schedule deployment days  in advance with an offshore vendor. If we mess up this delicate process, they don't install our software or just mess it up very badly.

I find it tedious to have to create this stuff, so I made a CI Factory package to do this. Since CI Factory has variables for all the important things in the build and in the project and has conventions for where stuff should go, I was able to make this package with very little code. It picks up various things from my code base for the rollout documents, concatenates all the SQL changes (our offshore team will only run one SQL script.)image

Being able to automate this easily has saved me a ton of time and we can now just do this on all our projects - a new automated precedent has been set.

In general, this kind of problem is very difficult for an off the shelf tool to be able to help with. You are going to end up writing a batch file or some  kind of a build script for this no matter what, just that when using CI Factory, custom build steps are kind of a first class citizen in the build, not some growth off to the side.

I am sure tools like Team City are really great and help lots of people and save puppies and baby seals, but that's actually the easy part of the build. The hard part is the last 10% and CI Factory really shines here.


 
Categories:

Update: Just found out March 5th is during MIX, and many people will be out of town. Changing to February 28 (which is a Thursday.)


If you are within driving distance of Bellevue on March 5th, come hang out at the Crossroads Mall Food Court, around 6:30pm. Oren Eini (a.k.a. Ayende) will be there and hopefully some of the same crowd as previous nerd dinners will show up. Pass it on!

Add to your calendar

 


 
Categories:

February 13, 2008
@ 10:40 AM

I always forget the name of the command to do this:

image

It's  View.ShowSmartTag. I like to bind it to Ctrl+1:

image

Hopefully I won't forget now.


 
Categories:

February 12, 2008
@ 10:00 PM

I am interested in joining/helping start a coding dojo (like this one) in Tacoma, Olympia, or Seattle. I am already talking with one person about doing it in Olympia, but I am curious if anyone else is interested, and especially about demographics. I would love to do something in Tacoma, because it would be totally easy for me for a change, but I seem to be alone in my willingness to drive an hour to hang out with .net geeks.

Anyone interested? If so, what's your commute radius?


 
Categories:

February 12, 2008
@ 09:55 PM

...Is open and almost full. Good luck getting in if you haven't already...

Anyway, I am excited to see several of the people I work with going: Trevor Redfern and Jeff Olson. Jeff and I are on the same team, and Trevor and were almost...maybe someday we will be.

Looking forward to this and getting to put faces to some of the names I see all the time.


 
Categories:

February 7, 2008
@ 09:53 AM

We have been building a new team at work which has me pretty excited. On the surface, the main benefit is that we get more people than, well, just me working on things for an exciting and growing line of business. But it goes way deeper than just that.

I have been using Cruise Control for a couple of years and this new team made me realize I was using it wrong. I had always thought it best to make a conscious decision when the build was ready for testing. Cruise Control could run all my unit tests and maybe a smoke test, but only a human could decide when a build was ready to pass on to another human to test.

One of the members of our team was formerly fixed in the role of tester in our department (now he is just a member of our team and I think he can do whatever necessary to make our team successful...a generalizing specialist) A couple of days ago, I finally got around to adding him to the e-mail publisher list for our builds. The process I was imagining was, "We should all know when the build is good or broken, but when I want to 'bless' a build for testing, I will just forward the Cruise Control e-mail notification with a little note or something. Without this blessing, the build is not ready for another human to spend time with." Unfortunately (or maybe, fortunately) I never got around to voicing this imaginary process.

Later, I started noticing that Jeff (the ex-"QA guy", current team member) would just run with the build notification and not wait for me to "bless" the build (it happened again just now.) I opened up a new e-mail and got ready to explain my imagined process when I realized that this was better. He _should_ be able to just grab a good build. Why would we check in a bad build?

One of the many excuses I use for checking in bad builds is that it's better to have the source code nice and safe in the source code repository than to have it sitting on one of my hard drives. Also, nice tight little single purpose commits make it easy to cherry pick things in case you need to merge them somewhere else later. Finally, nice little commits also tell a story better than a massive commit with a novella commit message.

So I could work out how to reconcile these two things - until just now. It sounds so simple it's stupid, but from now on I will concentrate on doing smaller _complete_ checkins. I will checkin as if I had 5 minutes left to live, and this checkin will be my sole legacy to man kind. I will imagine people looking at just the commits I have made and thinking "What the hell did he do that for?" whenever I feel the urge to check in something that passes unit tests but isn't deployable. If I absolutely have to leave without being done, I will use my version control systems fabulous branching support to "shelve" the changes I have made for later - but this will be reserved for "honey, I think I'm going into labor now"-type situations, since merging is still a little painful.

After all, these tools are all about reducing friction. If someone has to wait for an e-mail or some ceremony before they can do their work, then we're not reducing friction anymore.


 
Categories:

February 4, 2008
@ 06:52 AM

Here:

Each new term in the Fibonacci sequence is generated by adding the previous two terms. By starting with 1 and 2, the first 10 terms will be:

1, 2, 3, 5, 8, 13, 21, 34, 55, 89, ...

Find the sum of all the even-valued terms in the sequence which do not exceed one million.

I started this just as I was learning about workflow expressions in F#. When I read the problem, it looked like a nail, and recursive workflow expressions felt like a hammer in my hand (see bottom half of page 244 of Expert F#.) I thought that the Fibonacci sequence would make a great recursive workflow expression.

  1. I first coded up the Fibonacci function itself:

        public class Problem_002_Tests
        {
            [Fact] private void Fibonacci_of_Neg_1_should_be_0()
            {
                Assert.Equal(0, Euler.Problem002.fibonacci(-1));
            }
            [Fact] private void Fibonacci_of_0_should_be_0()
            {
                Assert.Equal(0, Euler.Problem002.fibonacci(0));
            }
            [Fact] private void Fibonacci_of_1_should_be_1()
            {
                Assert.Equal(1, Euler.Problem002.fibonacci(1));
            }
            [Fact] private void Fibonacci_of_2_should_be_1()
            {
                Assert.Equal(1, Euler.Problem002.fibonacci(2));
            }
            [Fact] private void Fibonacci_of_3_should_be_2()
            {
                Assert.Equal(2, Euler.Problem002.fibonacci(3));
            }
            [Fact] private void Fibonacci_of_4_should_be_3()
            {
                Assert.Equal(3, Euler.Problem002.fibonacci(4));
            }
            [Fact] private void Fibonacci_of_17_should_be_1597()
            {
                Assert.Equal(1597, Euler.Problem002.fibonacci(17));
            }
        }

    ...

    #light

    namespace Euler

        module Problem002
        
        (* The fibonacci function *)
        let rec fibonacci n = 
            if n = 0 then 0
            elif n = 1 then 1
            elif n > 1 then fibonacci(n - 1) + fibonacci(n - 2)
            else 0
  2. Next, I made a sequence:

            [Fact] private void SeventeenthElementOfFibonacci_sequence_is_1597()
            {
                IEnumerable<int> sequence = Euler.Problem002.fibonacciSeq(1, 2000);
                Assert.Equal(1597, sequence.ElementAt(16));
            }

    ...

        (* A sequence expression of fibonacci terms less than l *)
        (* I wanted to use a simple recursive workflow expression,
           but where I used it in answer, it would try to apply Seq.filter to the 
           whole infinite sequence. Therefore, I had to introduce the limit 
           parameter *)

        let rec fibonacciSeq(n, l)
            seq {
                let term = fibonacci n
                if term <= l then
                    yield term
                    yield! fibonacciSeq(n + 1, l)
            }

     

    As the comment says, I wanted this to just be yield fibnoacci n; yield! fibonacciSeq n+1; but had to introduce the limit.

  3. Finally, I made an even predicate and filtered and folded the sequence into the answer:

            [Fact] private void Answer_should_be_1089154()
            {
                Assert.Equal(1089154, Euler.Problem002.answer());
            }

    ...

        let even_p n = 
            n % 2 = 0
        
        (* Too bad there is not something like Seq.filter that assumes the sequence
           is in order, and could therefore stop iterating when the filter condition
           was met. If there was, I wouldn't need the limit parameter here. *)
        
        let answer()
            fibonacciSeq(1, 1000000) 
            |> Seq.filter(even_p) 
            |> Seq.fold (+) 0

     

    I think there is something like Seq.filter that's delayed...I think it's called Seq.delay!? But I don't really understand it yet. If I did have something like that, I could just make the answer include an extra |> Seq.filter (fun n -> n < 1000000).

     

I've started to swing towards the dark side with respect to single letter variable names, but since I still have meaningful method names and structure I feel OK about it.

Again, this is way less elegant than what you can see in the Project Euler forums, but I got to play with sequence expressions more and learned a few more things.


 
Categories:

February 4, 2008
@ 06:31 AM

Here.

If we list all the natural numbers below 10 that are multiples of 3 or 5, we get 3, 5, 6 and 9. The sum of these multiples is 23.

Find the sum of all the multiples of 3 or 5 below 1000.

This problem is pretty straightforward, but to get started, I needed to take the first step(s):

  1. Got the latest F# installed.
  2. Created an F# project.
  3. Created a C# xUnit.net test project (another thing I picked up at Code Camp.)

I tried to create an xUnit.net project in F#, but ran into some problem (can't remember what) and decided I was better off focusing my F# mana on the Euler problems than learning xUnit.net in F# and using F#. Doing the unit tests in C# was easy.

So, as a TDD'er, I broke the problem down into chunks I could write tests for:

  1. I needed a way to identify if numbers were multiples of each other:
        public class Problem_001_Tests
        {
            [Fact] private void Numbers_are_multiples_of_themselves()
            {
                Assert.True(Problem001.IsMultiple(3, 3));
            }
            [Fact] private void Any_X_Times_Y_Is_A_Multiple_of_X()
            {
                Assert.True(Problem001.IsMultiple(3, 3*23));
                Assert.True(Problem001.IsMultiple(23, 3 * 23));
            }
        }
  2. I implemented this in F#:
    #light

    namespace Euler

        module Problem001

        let IsMultiple n x = 
            x % n = 0

     

  3. Comfortable that basic math works, I wanted to try one of the features I really find appealing about F#: sequences:
            [Fact] private void AllMultiplesOf3Or5Under1000ShouldInclude525()
            {
                Assert.True(Problem001.AllMultiplesOfThreeOrFiveLessThan(1000)
                    .Contains(525));
            }
            [Fact] private void AllMultiplesOf3Or5Under1000ShouldNotInclude200()
            {
                Assert.False(Problem001.AllMultiplesOfThreeOrFiveLessThan(200)
                    .Contains(200));
            }
     
    ...
        let AllMultiplesOfThreeOrFiveLessThan n = 
            seq { 
                for x in 1..n - 1 do
                    if IsMultiple 3 x then yield x
                    else if IsMultiple 5 x then yield x 
            }

    Sequences seem a lot like IEnumerable<T> functions in C#, which I have been using a lot of.

  4. And finally, the answer:

     

            [Fact] private void FunctionalAnswerSameAsImperativeAnswer()
            {
                int accumulator = 0;
                foreach (int x in Problem001.AllMultiplesOfThreeOrFiveLessThan(1000))
                    accumulator += x;

                int answer = Problem001.SumOfAllMultiplesOfThreeOrFiveLessThanOneThousand();
                Assert.Equal(accumulator, answer);
                Console.WriteLine("The answer is: {0}", answer);
            }
            [Fact] private void TheAnswerIs233168()
            {
                Assert.Equal(233168, Problem001.SumOfAllMultiplesOfThreeOrFiveLessThanOneThousand());
            }

    ...

        let SumOfAllMultiplesOfThreeOrFiveLessThanOneThousand () =
            let range = AllMultiplesOfThreeOrFiveLessThan(1000)
            Seq.fold (+) 0 range

I like the way you can use the "+" operator as a first class function.

So that's it. Pretty dumb. Once I'd plugged in the answer to Project Euler, I took a look around the forums. My answer is dumb and verbose compared to some of the answers in the forums. Which brings me to an interesting conundrum:

In C#, and production development in general - I consider it poor style to write code that's really "mathy" - Single letter variable names, lots of terse iteration and use of abbreviated keywords. I like to have long descriptive method names and have the "nameable" parts of an algorithm broken out into named methods.

F# takes me the other way. It appeals to the side of me that likes elimination of waste. The side that throws boxes and packaging away as soon as I get something - preferably at the store. Once you understand the above problem, it's really just a one liner (see Project Euler forums.)

The C# (maybe I should say DDD) solution shows the work: You can literally see the steps taken to get the answer - not the program's steps, but the _programmer's_ steps. I think this is very desirable in a program, and will have to make sure I don't lose this in the elegance and sleekness of F#.


 
Categories:

February 4, 2008
@ 05:58 AM

Last weekend, one of the big things I got out of Code Camp was F# inspiration. I had just gotten my Expert F# book from Amazon and was very interested in F# anyway, but some of the presentations (Ted Neward's F# and Scala talks, Wesner Moise's talk, and some other things) got me really exited.

I have started trying to do some finance stuff with F#, but that's pretty boring :-)

One thing I've found useful, as I don't have a heavy math background, is Project Euler, a web site with some simple math problems that lend themselves to computational solutions. I don't have great answers, but doing these Project Euler problems is really helping me focus on getting used to F#. There are lots of frustrations but overall, it's a lot of fun.

I'm sure no one else is interested in watching me butcher F#, but I'm going to post my solutions anyway, since it's my blog and I have nothing better to post. If you don't like it, shoot me an e-mail and I'll send a full refund plus a years supply of blog posts!

I am putting all the code for this in my google code: http://code.google.com/p/cbilson.


 
Categories: