The Endless Obsession

better code

Learning F# with TDD: Part 1

I decided to dive into a few languages I’ve been meaning to learn by way of the calculator kata. First up: F#.

First, some prerequisites.

  • F#, obviously. This comes with VS 2010 so you probably already have it.
  • We’re doing TDD, so we need some sort of testing framework. I decided to go with NaturalSpec. This means we’ll need to download the package from github, build it, and also download and install NUnit and TestDriven.NET. The author has a good blog post on setting up and running the test project.

Keep in mind that I’m extremely new to the language, so the code I ended up with probably doesn’t reflect what a seasoned F# programmer would write. I tried to follow conventions that I could pick out as much as possible. The first part of the kata is an add function. Pretty simple. In the interest of not getting bogged down in one language I didn’t take if very far, so I will only be able to make very broad observations at this point.

Two positive things that I took away from it: pattern matching and pipe.

Pattern matching is something that I knew was popular in functional programming circle but had never experienced first hand. Now that I have a taste of it I think it’s a handy abstraction, but I have a feeling that I haven’t even begun to scratch the surface of what it could mean.

let addNumbers (numbers : List) =
    match numbers.Length with
    | 0 -> 0
    | 1 -> numbers.[0]
    | _ -> numbers |> Seq.reduce (fun a b -> a + b)

This is simply an alternative form of the familiar if-else branching logic, nothing special really, but it is pleasantly terse.

Pipe is even more exciting. Take the following for example.

numbers.Split ',' |> Array.toList |> List.map int |> addNumbers

Using the pipe operator (that’s “|>”) you can stream a value through a series of transformations, in this case splitting the string, converting the array to a list, converting the items in the list to integers, and finally passing the list to a method called “addNumbers”.

In any other language this would probably read similarly if your transformations are all instance methods, however, that breaks down as soon as you have to use global or static/class methods. The pipe form always reads nicely from the beginning to the end. Of course, this example could be a little simpler since our function can technically accept an array as its argument.

To be continued…

Disable the audible beep in Mac Terminal

This was starting to get on my nerves. I really don’t need a fancy sound clip to keep reminding me that I deleted as far as I can go. I always do that, since I’m a bit OCD. This one took me too long to find, mainly becuase of tabs.

Anyway, to disable the sounds, go to Terminal -> Preferences -> Settings (top tab group) -> Advanced (inner tab group), look for the “Bell” group label and uncheck the “Audible Bell” option. Note that this is specific to a particular settings configuration/theme, so if you switch themes the behavior will change.

Tfs Rollback

Using the tf command line tool you can rollback all or part of a tfs checkin. This is useful for two reasons: 1) If you at least want to roll back all changes in one or more file (not some changes in a file) then it saves you from having to manually revert changes (I’m a firm believer in not giving yourself the opportunity to goof up) , and 2) the checkin is actually marked as a rollback, so you don’t have to rely on checkin notes to identify it as such.

As a side note, based on what I’ve seen in the way that tfs represents changes, this rollback changeset is simply an add, edit or delete, with the additional information that it was a rollback of a prior change. The original checkin is still in the tfs history.

To do a rollback, first open up the visual studio command prompt. You should have a shortcut in your start menu. On my machine the command is: %comspec% /k “”c:\Program Files (x86)\Microsoft Visual Studio 10.0\VC\vcvarsall.bat”” x86.

Here’s the help for tf rollback (using the command tf rollback /?):

TF - Team Foundation Version Control Tool, Version 10.0.30319.1

Copyright (c) Microsoft Corporation.  All rights reserved.

Rolls back the changes in a single or a range of changesets:

tf rollback /changeset:changesetfrom~changesetto [itemspec] [/recursive]

            [/lock:none|checkin|checkout] [/version:versionspec]

            [/keepmergehistory] [/noprompt] [/login:username,[password]]

tf rollback /toversion:versionspec itemspec [/recursive]

            [/lock:none|checkin|checkout] [/version:versionspec]

            [/keepmergehistory] [/noprompt] [/login:username,[password]]

Versionspec:

    Date/Time         D"any .Net Framework-supported format"

                      or any of the date formats of the local machine

    Changeset number  Cnnnnnn

    Label             Llabelname

    Latest version    T

    Workspace         Wworkspacename;workspaceowner

First, we need to make sure we are working within our workspace.

C:\> cd workspace

So, for example, we could rollback an entire changeset:

C:\workspace> tf rollback /changeset:12345

Or, we can rollback a single item in the changeset:

C:\workspace> tf rollback /changeset:12345 $/Path/To/Item

There is also a login param that you can pass if needed:

C:\workspace> tf rollback /changeset:12345 /login:domain\username,
password

Enjoy!

Visual Studio External Tools

Here’s a neat visual studio tip. You can run any external command from within visual studio, and add a button to the command bar or map it to a keyboard shortcut. This is really important to me because I rely heavily on keyboard shortcuts. I love that I can hit a combination of keys and perform a repetitive task automatically, plus the result can be incorporated into visual studio by way of the output window.

Some examples of what you might use this for:

  • Get latest on several team projects to start your day.
  • Check out a specific set of files.
  • Automate various git commands from within visual studio.
  • Run a batch file with a set of arguments that you define when you run it.
  • Launch another application (i.e.: web browser).

What follows is inspired by Rob Conery’s Git series on tekpub. You’ll have to watch the full video to see how he uses external tools to incorporate git in Visual Studio.

Continue reading

ExoWeb's Entity System

Matt Hooper recently posted an overview of ExoWeb’s entity system.

From the post:

We’ve done our best to make sure the parts and pieces that comprise the ExoWeb entity system work consistently, fit together cleanly and take advantage of JavaScripts language features.

Go check it out!

Intro to Client-Server Mapping in ExoWeb

As a follow up to my Brief Introduction to ExoWeb, I would like to go into more detail about the communications between client and server.

The client interacts with the server in two basic ways.

  1. Pulling information: type and instance data.

  2. Pushing information: changes to the model and/or instructions to do something.

The first type, pulling information, is pretty straightforward. Type information doesn’t change (frequently) so it is actually cached on the client if possible. Querying for instance data is similar to querying a database. You request an object of a particular type with a particular id, but you can also include a set of paths that tell the services what additional related data you are interested in. The primary component of a query might look something like this.

{ from: "Person", id: "1", and: ["this.Additional.Properties.To.Load"] }

The second type, pushing information, gets a little more interesting. If you’re going to sync data between two disconnected systems there are two primary approaches that you might take. First, you could send simple data from point A to point B, manipulate it, then send it back from point B to point A in the same form. As you could imagine this can get pretty expensive and tedious. Of course, you might just send the portions of data that have changed to cut down on overhead. The bigger problem, I think, is that you don’t really know what has happened unless you do full graph comparisons. Another approach is to keep track of changes as they occur and send those back and forth. This is what ExoWeb does.

changes: [ { type: "ValueChange", instance: { id: "1", type: "Person" }, property: "FirstName", oldValue: "Rob", newValue: "Robert" }, ... } ]

The client can also raise events, for example “save”, a built-in event. In response, the server can send back additional changes to the model.

changes: [ { type: "Save", idChanges: [ { type: "Person", from: "?4", to: "644" } ] }, ... ]

The payload isn’t limited to data. It can also include conditions, for example, permissions, or invalid data conditions. More on that later.

This has been a very basic introduction to the way client-server communication works in ExoWeb. Look out for more updates in the future.

A Brief Introduction to ExoWeb

A while back I talked about the ExoWeb project and scripts that are now hosted on github. That post was a little vague because not much has been documented about what you can actually do with ExoWeb. That’s what I hope to do here.

First off, let me restate the purpose of ExoWeb as simply as I can. ExoWeb exists to bridge the gap between the client and server. You can think of it as a combination client-server mapper and model-view mapper.

Continue reading

Getting started with virtualenvwrapper

A while back I toyed with using virtualenv and virtualenvwrapper to manage isolated python packages for development, but I didn’t get very far at the time. Recently I’ve been dabbling in ruby and have used RVM to manage ruby environments and gems. This experience has been a positive one, so I decided to revisit virtualenvwrapper to see how it would compare.

Continue reading

I wish I could remember what Amnesia is...

One of my coworkers, Matt Hooper, recently released an open source project called Amnesia. The aim of Amnesia is to “transacts all changes to a website to facilitate automated UI testing”. Basically, you can run your tests and change and add data all day long and the changes, whether they come from the website or the tests themselves, will not last beyond the scope of the test. Pretty cool, huh?

The blog post where he announced it can be found here, and the source and documentation is hosted on Codeplex.