My Technology Stack

image I am writing this post in response to David Burela’s ‘What is your preferred technology stack?’ meme.

As an independent developer I generally have a lot of flexibility to chose the tools that I think will deliver the best result, with the restriction that my customer is generally looking for a .NET based solution. I favour tools which:

  • are open source. Open source libraries are often designed to facilitate quality practices, not to sell tools. Also, access to the source and the price are bonuses.
  • support the software craftsmanship ideology. Small, sharp tools that stay out of the way and don’t force any design decisions.

Here is my current preferred technology stack, from the outside in:

  • jQuery + lots of plugins on the client. I hope to introduce CoffeeScript on a project soon.
  • I don’t have a firm opinion on view engines. nHaml is great in theory, but poor in execution. Spark is also fantastic, but I might switch razor in the future if I like it.
  • Asp.NET MVC. Leaving webforms behind was the best technology decision I have ever made.
  • Structure Map for IoC. I don’t have a strong opinion on this. I continue to use Structure Map because it is familiar.
  • ELMAH for logging exceptions.
  • Moq for mocking. AutoMockContainer for auto mocking.
  • StoryQ for BDD style testing
  • NHibernate + FluentNHibernate for data access. The more I use these tools that more I favour explicit mapping over auto mapping. I don’t like NHibernate but at the moment it seems to be the best of a bad bunch.
  • A custom framework for constructing objects for use in testing.
  • SVN for version control. I have used mecurial for some projects but svn is familiar and does everything that I need.
  • Pivotal Tracker, Green Hopper or Unfuddle for project management
  • Rake + albacore for build scripting. I have a screencast on this that will hopefully one day see the light of day.
  • Teamcity for continuous integration.

Behaviour-Driven Development with StoryQ

Over the weekend of the 24th and 25th of July I gave two presentations at the South Australian Code Camp. The first was on the subject of behaviour-driven development, with examples using StoryQ. Here are my slides and sample application: 

Slide1 Slide2 Slide3
Slide4 Slide5 Slide6
Slide7 Slide8 Slide9
Slide10

Example Application


Thoughts on a Sinatra-like DSL for Server-Side Programming with CoffeeScript

I read somewhere that Kent Beck likes to apply a strategy of taking a technique that works and exaggerating it, to see if the results are likewise exaggerated. He found that specifying the behaviour of components prior to implementation, and in small increments, produced good design, so he exaggerated it and now we have TDD. He found that strong engineering practices, rich communication and delayed decision making was a good way to run projects, so he exaggerated it and now we have Extreme Programming.

In homage to Kent Beck and his work I decided to apply his technique to web frameworks, taking the things that I like and exaggerating them. Here are some of the things that I value in a web framework:

  • a rich language
  • simplicity
  • minimalism
  • expressiveness
  • opinionatedness

Using the above guidelines I sketched out an idea for a server-side framework for CoffeeScript. It is heavily inspired by Sinatra, with a few minor tweaks and coverted to CoffeeScript. Here is what a controller might look like:

# The first parameter is the route. Like sinatra, there is no route abstraction.
# The second parameter is a method to execute when the route is matched.
# Enforced one-model-in. No need for params[]

get '/', (input_model) ->	
	"Hello World"
	
# Views are found based on the name of the model passed to the view method.
# ? here is the CoffeeScript existential operator.

get 'address/:slug', (address_request) ->
	if address_request?
		@address = address_finder.find_by_slug address_request.slug			
		view @address	
	
# View model objects are automatically given bind_to() and update() 
# methods for binding to and from domain objects.

post 'address/create', (address_model) ->
	@address: address_model.update new Address()
	# do something with @address
	@address_list = address_finder.all()
	view @address_list

As promised the implementation described has some strong opinions: one-model-in, binding methods on view models and no route abstraction.

One-Model-In

One-model-in is a rule that no action may have more than one parameter. All request values (querystring, form, route) are mapped onto the input view model.

Binding Methods on View Models

The input view model objects are automatically given bind_to() and update() methods. By extending the base view model class developers can create more sophisticated view models.

view_model_object.bind_to(domain_object)

Bind to copies the attributes of the input domain object to the view model object.

view_model_object.update(domain_object)

Update copies the attributes of the view model object to the domain model object.

No Route Abstraction

Most MVC web frameworks have an abstraction for routes, meaning that a url is mapped to a route and the route is mapped to a controller action.

Url <—> Route <—> Action <—>

Sinatra simplifies by omitting the route abstraction, and I have too. The advantage is simplicity, the disadvantage is that refactoring an application’s URL scheme might be more difficult.


KeyRef Progress Update

Here are the original mockups for KeyRef

select_app

view_shortcuts

and the implemented screens look like (apologies for the ugliness):

image

 

image

both the application search, and the shortcut search, are working.

I tweaked the application shortcuts page url, so now the url for visual studio shortcuts is:

http://localhost:3000/app/show/4c19e8a5cfbfb01794000001/Visual%20Studio-shortcuts

Also, I have a page for entering new shortcuts that looks like:

image

Now I can start adding shortcuts, which will be a big job. I’d like to get it online so that people can add shortcuts for their favourite applications.


Managing .NET Deployment Configuration With Rake

Rake is a ruby internal DSL for build scripting. With (or without) the help of albacore rake makes an excellent build scripting tool for .NET projects.

The albacore documentation does a good job of explaining how to build solutions with rake but there is nothing to assist with another common build task – updating configuration files.

The following ruby script provides some helper methods for performing common configuration changes that are required as part of a build process. 

class ConfigTasks

	def self.set_app_setting(config_file, key, value)
		ovsd_element = config_file.root.elements['appSettings'].get_elements("add[@key='#{key}']")[0]
		ovsd_element.attributes['value'] = value
	end
	
	def self.set_connection_string(config_file, name, connection_string)
		conn_string_element = config_file.root.elements['connectionStrings'].get_elements("add[@name='#{name}']")[0]
		conn_string_element.attributes['connectionString'] = connection_string
	end
	
	def self.set_debug_compilation(config_file, debug_compilation)
		compilation_element = config_file.root.elements['system.web'].get_elements("compilation")[0]
		compilation_element.attributes['debug'] = false
	end
	
	private
	
	def self.write_xml_to_file(xml_document, file)
		File.open(file, 'w') do |config_file|
			formatter = REXML::Formatters::Default.new
			formatter.write(xml_document, config_file)
		end
	end

end

To use, require the file and call the class methods, passing the configuration file name and any other parameters.

require 'config_tasks'

ConfigTasks.set_app_setting 'web.config', 'enableCache', 'false'

Twitter Customer Sentiment Analysis

The breakable toy that I am currently working on is a twitter customer sentiment analyser.

It scrapes twitter for tweets relating to a particular organisation, applies a machine learning algorithm to determine if the content of tweet is positive or negative, and generates reports of the sentiment data over time, correlated to dates, events and news feeds.

I’m having lots of fun building this, but I would also like to learn if there is a market for quantified sentiment data. So that I can start to show people what I have in mind I have created a mockup of the simplest and most important report. It shows customer sentiment over time, with important events highlighted. As the user moves their mouse to the right (forward in time) the source data area scrolls up to display the tweets from that time. The tweets are colour coded based on sentiment rating.

design

After I started working on this project I discovered that a team of students have already built something similar. It is a lot of fun to enter your employers name and see what it says.


Random MongoDb Syntax: Updates

I have a MongoDb collection called tweets. Each document has a property system_classification. If the value of system_classification is ‘+’ I want to change it to ‘positive’.

For a regular relational database the query would be:

update tweets
set system_classification = 'positive'
where system_classification = '+'

the MongoDb equivalent is:

 db.tweets.update({system_classification: '+'}, 
 {$set: {system_classification:'positive'}}, false, true)

 

Parameter Description

{ system_classification: '+' }

the first parameter identifies the documents to select

{ $set: { system_classification: 'positive' } }

the second parameter is an operation ($set) and the parameter to that operation {system_classification: ‘positive’}
false the third parameter indicates if this is a regular update or an upsert (true for upsert)
true the final parameter indicates if the operation should be applied to all selected documents (or just the first)

Command Query Separation

image Command query separation is a strategy, proposed by Bertrand Meyer, that each of an object’s methods should be either a command or a query. A command is an operation that changes the state of a system, and a query is an operation that returns a value.

This is not the same thing as CQRS, hence why I think that CQRS is poorly named.

An Example of Command Query Separation

Consider a system that models books and shelves. There is a rule that a shelf may not be removed if it holds any books. One way to implement the removal is to write a method Shelf.Remove() that internally checks to make sure that the shelf is empty before removing it. If the shelf is not empty then it is not removed and an error is returned. To implement this feature following the principle of command query separation would require two methods, one to query the shelf and determine if it is empty and a second method to remove the shelf. Separating the query from the command makes the shelf class simpler to use because the state change is clear and explicit.


mongoDB Management Studio

This weekend I have been in Sydney at the MS Web Camp, learning about web application development. At the end of the first day we came up with application ideas and pitched them. My idea was to build a web management application for mongoDB.

mongoDB

I pitched my idea, put down the microphone, and then someone asked, “what’s mongo?”. Good question. MongoDB is a document database that stores JSON style documents. This is a JSON document for a tweet from twitter:

 db.tweets.find()[0]
{
        "_id" : ObjectId("4bfe4946cfbfb01420000001"),
        "created_at" : "Thu, 27 May 2010 10:25:46 +0000",
        "profile_image_url" : "http://a3.twimg.com/profile_images/600304197/Snapshot_2009-07-26_13-12-43_normal.jpg",
        "from_user" : "drearyclocks",
        "text" : "Does anyone know who has better coverage, Optus or Vodafone? Telstra is still too expensive.",
        "to_user_id" : null,
        "metadata" : {
                "result_type" : "recent"
        },
        "id" : {
                "floatApprox" : 14825648892
        },
        "geo" : null,
        "from_user_id" : 6825770,
        "search_term" : "telstra",
        "iso_language_code" : "en",
        "source" : "&lt;a href=&quot;http://www.tweetdeck.com&quot; rel=&quot;nofollow&quot;&gt;TweetDeck&lt;/a&gt;"
}

A mongodb server can have many databases, each database has many collections (instead of tables) and a collection has many documents (instead of rows).

Development

Day 2 of the Sydney MS Web Camp was allocated to building our applications. First thing in the morning I identified the stories that I wanted to implement:

Scenario: View databases
Scenario: View Collections in a database
Scenario: View Documents in a Collection
Scenario: Delete a Collection
Scenario: Delete a Database
Scenario: Delete Documents

Over the course of the day the team (3.5 developers) implemented all of the planned stories (except ‘delete a database’) and also implemented the following:

Scenario: Create Database
Scenario: Create Collection

Lessons Learned

I’m new to MongoDB and in the past I have only accessed it from Ruby (for my hare-brained scheme). When it came to implementing our MongoDB management studio we discovered that their is no official MongoDB driver for .NET. We chose to use NoRM, honestly just because it was the only one I had heard of. NoRM was a challenge. I think it is a fine library but it is focused on mapping strongly typed objects to MongoDB. For our application we had no prior knowledge of the types that would be in the MongoDB database so NoRM was probably a poor choice.

Here are some screens (click to enlarge):

image image


Unnamed Refactoring

This post is a message in a bottle. I cast it into the sea in the hope that it will one day return to me, stuffed to the cork with enlightenment. Yesterday I  tweeted,

what is the name of the pattern where you replace a multi-way conditional with an associative array?

I said ‘pattern’ but I meant ‘refactoring’. Anyway, no one replied so I will describe the refactoring here.

Programmers tend to think imperatively, which leads to code such as:

public int GetPopulation(string country)
{
   if (country == "Australia")
   {
       return 22360793;
   } else if (country == "China")
   {
       return 1324655000;
   } else if (country == "Switzerland")
   {
       return 7782900;
   }
   else
   {
       throw new Exception("What ain't no country I ever heard of. They speak English in what?");                    
   }
}

which is horrid. We can write a cleaner version, replacing the multi-way conditional with an associative array, treating the conditional as data:

public int GetPopulation(string country)
{
   if (!Populations.ContainsKey(country))
       throw new Exception("The population of " + country + " could not be found.");

   return Populations[country];
}

private Dictionary<string, int> Populations
{
   get
   {
       return new Dictionary<string, int>
           {
               {"Australia", 22360793},
               {"China", 1324655000},
               {"Switzerland", 7782900}
           };
   }
}

 

Does this refactoring already have a name? Otherwise, I propose

Replace multi-way conditional with associative array