Wednesday, August 16, 2006

Looking for work

I'm looking for work and open to offers.
You can email me on 'jobs at nigelthorne.com'

Thursday, August 03, 2006

Keeping Dynamically Loaded Plugin Assemblies unlocked in ASP.Net

I have written a plugin system for an asp.net application. The system basically searches a plugin directory for assemblies containing types implementing the IPlugin interface. To do this it needs to load the assemblies at runtime. The problem I had with this was that it locked the files once they were loaded. If I then compiled a new version it failed to copy the assembly to the desired location as the file there was locked by the asp.net worker process. I tried various solution to do with creating my own appdomain. I didn't get much success with these. You will have to do this if you want to unload your assemblies at any point though, as AppDomain.Unload unloads the whole domain.

Anyway... it turned out that the best solution for me was to get asp.net to shadow copy the assembly for me. This was as simple as putting the following code in your ApplicationStart in Global.aspx.cs


AppDomain.CurrentDomain.SetShadowCopyPath(
AppDomain.CurrentDomain.SetupInformation.ShadowCopyDirectories
+ ";" + Server.MapPath("~\plugins"));


For further information look here, here and here.

Wednesday, August 02, 2006

Feed link changed

please update your atom/rss links to : http://feeds.feedburner.com/nigelthorne/blog

Friday, July 28, 2006

Another Rails Conf Talk Released

I'm loving ScribleStudio's coverage of the RailsConf2006 Keynotes.

One of the questions to the Rails core team was 'do you guys hate fixtures?' or something like that. I was amazed that they too dislike them. DHH summed it up well... to paraphrase.. Fixtures shouldn't be shared across tests, but they are so hard to set up that you end up doing it anyway, which doesn't scale. The cost of making fixtures needs to be lowered. They didn't have any ideas how to do this.

This make me recall my suggestion from a few days ago... instead of fixtures, define an object mother (some class that can generate test data for you given some criteria) and dependency injection or some other terse mechanism to specify your context for your test.

Looking at the way rSpec is going, this maybe the best condender for this sort of thing. I'll keep thinking about it. Keep tuned to see any further developments.

... and as always feel free to leave comments

Thursday, July 27, 2006

DSLs in Ruby

There are two approaches to writing DLSs, Internal and External to the implementation language.

With internal DSLs the ruby parser is used (eg. ActiveRecord). It is surprising just how much you can personalise your language and still remain within the syntax of ruby.

see 'Creating DLSs In Ruby'

External languages require you to write a parser. This sounds hard, but there are a few libraries available that simplify the process. Check out multi and sexp gems.

see 'If It's Not Nailed Down, Steal It'

Wednesday, July 26, 2006

More on BDD

Dave Astel gave a talk on BDD for Google.
check it out...

Tuesday, July 25, 2006

Introduction to BDD (Behaviour Driven Development)

BDD is an evolutino of TDD. Those that are doing TDD correctly are aware they are writing in code small specification documents. The code is then written to meet the specification, then the code is checked automatically against the specification using a tool that understands both documents. To call these specifications tests is backwards, as there is nothing to test at the point they are written. More importantly as tests they have an implied scope (unit tests test methods on classes one at a time). If you write specifications instead, then a different scope seem far more appropriate (eg. In context X these things should be true.)

When I first heard about this concept the implementations of frameworks were nothing more than Nunit and Junit with the names changed. Looking at rSpec however things have come along well. Yet again Ruby lends itself well to creating a DSL. In this case for code specification.

Here is an example from rSpec's "RSpec on Rails".

context "The Person model" do
fixtures :people, :animals

setup do
# fixtures are setup before this
end

specify "should find an existing person" do
person = Person.find(1)

person.should_equal people(:lachie)
person.name.should_equal 'Lachie'
end

specify "should have animals" do
people(:lachie).should_have(2).animals
end

teardown do
# fixtures are torn down after this
end
end


I love it!

Check out Dave Astel's great introduction to BDD.

SVN Berkley DB Lock

The server's drive got full and that broke subversion last night. The Berkeley databases got locked and wouldn't unlock. I couldn't do an svn recover \repository\path as it wouldn't release the lock.

Finally I realised all I needed to do was reset the svnserver service.
I lost a good hour of my life looking for solutions, hopefully you won't have to.

xUnit with a twist

Imagine nUnit coupled with Object Mother and dependency injection.

You would be able to write a test and specify the test objects you wish to manipulate by adding parameters to the method.

[Test]
public void adding_a_task_to_a_project_causes_the_tasks_predicted_start_date_to_be_set( IProject mockProject, Task washCloths )
{
// ... test stuff as normal
}

Parameters with the name 'mockX' could cause mock instances to be created. 'washCloths' would be an example of a named instance, so a specific instance of task would be created in a known state. 'anyProject' could return a simple project instance.

Just a thought... but I like it.

Thursday, July 13, 2006

Now there is no excuse not to try Ruby!

Check out http://tryruby.hobix.com

It's a ruby interactive tutorial in a browser (thanks to 'why the lucky stiff')


Wednesday, July 12, 2006

Buildix: Development Infastructure in an instant

Check out Buildix.

Subversion, Cruise Control, Tracs all preinstalled and running from a KNOPPIX disk.

Monday, July 10, 2006

IDEA: Bleeping Media Player

"Cutting out the Naughty Bits Ruled Illegal" on slashdot today refers to a case where people were creating DVDs of special edits of films with the sex scenes, bad language, etc. cut and swapping them for original dvds.

Personally I feel there is a market for a device (or initially media player) that can gain access to bleep tracks for movies, cd's etc and use them to (at runtime) modify the output of the player.

So imagine... you buy your daughter a new music cd. You have previously configured her player to her age group. When the player gets to track 6 (which unknown to you contains the f word) it blanks the word (or play some substitute mp3 to patch it) . In a DVD with explicit content it could blur the screen, or cut the scene or whatever.

The community could create the patch-tracks and make them downloadable for each media... by default the player could dissallow anything not on the list.

This would only work for youngsters that are not able to buy their own player, but those are the ones you would want this for anyway.

It doesn't infringe copywright or anything, so all legal. :) It solves the same problem.

Monday, July 03, 2006

OSX keyboard shortcuts

Here's a list of keyboard shortcuts for OSx.

I was looking for 'Cycle to next windows of same application' which turned out to be Control + `

New MacBook

I recently got a new MacBook (duel core OSX).. so far I am loving it!. It's so much faster than my old PC laptop (which wasn't that quick anyway, so thats not saying much). In other words, all the Rails stuff generators etc run in seconds (or fractions there of) not minutes. I am getting used the different window paradigm. Learning the new key mapping seems the hurdle. I used to use linux back at uni (in 1994) so terminal is like an old friend. I love the software installation process (drag things from mounted drives to the applications directory). it is so light! I can hardly feel I am carrying it around. My old laptop powersupply probably weighed the same as my macbook. Things I would change are:

The mouse sometimes seems to freeze for a second after switching application. The screen is wide, but small, so the text is tiny. I think i would have appreciated getting the Pro with the larger screen. The macbook doesn't have enough space for my hands to rest while I type so my palms get a bit sore resting in the sharp corner the edge of the machine presents when open.

Another big win is knowing that if I shut the mac, no matter what is running it will hibernate. With windows if I had a browser open or webrick running it somtimes failed to hibernate. This meant I had to sit there attempting to hibernate it and killing processes till it worked. Not ideal.

Oh and battery life! My laptop was down to about 1hr before it died. The macbook lasts abount 3 to 4 hours, so thats a big improvement.

All in all, I am very happy with it.

Rails Hint: Database changes from script/console

You can make database changes from script/console like this...
ActiveRecord::Schema.define do 
drop_table :follies
end

Friday, June 30, 2006

More Getting Real

37 Signals keep banging on about 'getting real' or making small things that work well with small teams. Paul Graham has a great post on his blog called The Power of the Marginal. His writing style is great. There were more than a couple of places that made me giggle.

Thursday, June 29, 2006

What do you mean, 'What's Rails?'

Through a conversation with a .Net buddy of mine it became apparent that not everyone knows what Rails is...so .. Here is my 1 min pitch for developers.

Ruby on Rails (or just Rails for short) is a web development framework built on the MVC architecture. Ruby is an inturpreted implicitly typed language that the framework is written in.

M is for model

The beauty of the Ruby programming language is how easy it is to extend the language to create other domain specific languages (DLSs). This is used in Rails to create a DSL for defining strongly typed domain objects (model) that also automagically works as your DAL (data access layer) by mapping each class to a table and each instance of the class to a row (i.e. using the Active Record design pattern).

class Person < ActiveRecord::Base
end

That is enough code to give you a Person class with a 'find' method that will load instances from the 'Persons' table in the database, and properties for each column in the database.

So... you can do:
p = Person.find (1)
p.name = 'nigel'
p.save

... to change the name of the person with id=1 to 'nigel'.

class Person < ActiveRecord::Base
has_many :blogs
belongs_to :family
validates_length_of :name, :maximum= > validates_numericality_of :age
validates_presence_of :family
end


would add methods to the class to allow you to navigate the relationships to joined tables. The lovely part is that this class is just a class, so you can add whatever business logic to it you want to add and it all just works. You can hook into events like validate, save, etc. and put in custom code too.

V is for view

The View is provided by an ASP-like templating system called 'rhtml'. Basically its just HTML with ruby sprinkled through it. Again the versitility of ruby makes this painless to use. (There are other solution to the view for Rails, but this is the default)

so... app\Person\edit.rhtml might be..


<h1>Edit Person<h1>
<%= start_form_tag :action =>'update' %>
<%= error_messages_for 'person' %>
<p>
<label for="person_name">Name</label>
<%= text_field 'person', 'name' %>
</p>
<%= submit_tag 'Edit' %>
<%= end_form_tag %>

... which will create a form with a post action of '\person\update\1' (where 1 is the ID of the record being edited) passing the form fields (name in this case) as post fields.

To avoid duplication you have 'layouts', 'partials', and 'helpers'.. (not covered here)

C is for controller

The Controller is where your code kicks in to handle each web request. The requested url is put through some customizable routing code, that by default causes a method to be called on a controller passing a 'params' hashtable of values from the form. By default there is a view associated with each method of the controller.

So for example :

http://www.example.com/people/edit/1 would cause an instance of the 'PeopleController' class to have its 'edit' method called passing in a hash containing id=1.

Typical code inside the controller would then call '@person = Person.find(params[:id])' setting a local variable 'person' to the instance of the active record class Person that is retrieved from the database.

The framework would then by default render the associated view 'app\views\people\edit.rhtml' automatically populating the 'text_field' with the value of @person.name. The user can then change the name and click 'Edit' to trigger the form to post the new vaules. These are then fed in a params hashtable to the PeopleController class again where the 'update' method is called (as it is the action of the form). Some simple code in the PeopleController like ...

def update
@person = Person.find(params[:id])
@person.update_attributes(params[:person])
end

... is enough to save the new values back to the database.

You would probably want to do something like this instead though...

def update
@person = Person.find(params[:id])
if @person.update_attributes(params[:person])
flash[:notice] = 'The person was sucessfully updated.'
redirect_to :action = 'show', :id = @person
else
render :action = 'edit'
end

end


Any validation erros would then cause the user to be sent back to the same edit form with validation errors displayed. Yes, magically (see the "error_messages_for 'person'" line).

ok thats enough to get you started I'm sure, and I havent even touched on migrations, or ajax support, or the built in testing fixtures. Google for 'Ruby on Rails', or check out http//www.rubyonrails.org/ for more info.

Happy Railing.

Ruby on Rails just keeps getting cooler

DHH's latest extensions to Rails take advantage of the CRUD nature of the HTTP protocol to make URLs more powerful. A recent extention to the routing system allows you to base your rules on the HTTP method {GET, POST, PUT, DELETE} aswell as the url of the request. This opens up the possibility of calling several different controller methods from the same URL.



This has several beneficial results.

Check out DHH's slides for some more info.

Note: Most proxy servers don't handle Put and Delete methods correctly, so DHH has put in a work around using Post and some hidden form fields.

Wednesday, June 21, 2006

RailsDay: 24 hours of solid Railing

Myself and a couple of friends (Craig and Simon Hildebrandt) spent 24 hours straight coding Ruby on Rails. We met up at a house in the city and coded from 2pm Saturday to 2pm Sunday. There was however method to out madness; we were competing in 'Rails Day 2006'.

We wanted to create something that we would find valuable in our own projects, and that we could use over and over again, and I am happy with the result.

The aim was to create, what will eventually become an engine, that will allow us to create custom CRM solutions for a fraction of the development time.

Our submission to the Rails Day contest looks like a very simple CRM application. Admin users are presented with a very simple/clean/intuitive interface to modify any data in the database, including relationships (task 1 belongs to a project 2, etc.). The Magic is that the whole admin section is auto-generated directly from the model, no coding required.

The admin controller looks for model classes and adds then to the list of editable types. For each type is displays a list of all instances and an edit/create form. It uses information from the column type and validation rules to decide which widget is required for each attribute of the model object. 'belongs_to' relationships are displayed as drop downs. 'has_many' is displayed as a list with an 'add to list' widget. We also demonstrated that this can be extended to account for 'acts_like' mix-ins and plug-ins by handling the 'file-column' plug-in.

We are hoping that by open-sourcing this projects we will be able to get people to extend the number of plug-ins, acts_like's, validation rules, etc., that the framework handles.

Already we are finding this engine valuable in our own projects, soon, I hope, you will in yours.

... keep watching for a rubyforge link soon...

Cheers,
Nigel

Thursday, June 15, 2006

Fed up with blogger

I am going to move my blog. Blogger keeps loosing my account so I can't log in.

Wednesday, May 10, 2006

Typing games

I currently type at a speed of around 50 words a minute and an error rate of about 4%. That isn't too bad, but I hate the constant backspacing I feel I am doing. I went looking for some online typing tutors... they are all pretty boring. Some fun online typing games though can be found at http://2addicted.com/words and http://2addicted.com/letters

Rojo the feed reader

I have been looking for a good online feed reader. At the moment I am using Rojo. It seems to do most of what I want. Check it out at www.rojo.com (and yes it's free)

Tuesday, May 09, 2006

How to change the logical file names in MSSQL

Just incase this is valuable to anyone else, here is a script to change the logical file names in an mssql database.

declare @n1 varchar(100)
select @n1 = name from sysfiles where name not like '%_log%'
declare @n2 varchar(100)
select @n2 = name from sysfiles where name like '%_log%'

exec ('ALTER DATABASE [Test] modify file (NAME =''' + @n1 + ''', NEWNAME = ''Test_Data'')')
exec ('ALTER DATABASE [Test] modify file (NAME =''' + @n2 + ''', NEWNAME = ''Test_Log'')')

select name from sysfiles -- just to check

Assumptions:
  • 'Test' is the database name
  • You have two files
  • The log one ends in _log
  • The other one doesn't

Thursday, April 20, 2006

Share what you love

I read recently something along the lines of 'Doing what you love does not lead to wealth unless you also share what you love with others.'

It really seems to ring true for me. If you love sport, but spend all day watching it alone then you are not going to get rich. If you spend all day sharing your love of sport with others (coaching, compeating, or commentating) then yes you can make money at it. Infact the more people you share it with the more money you can make.

Wednesday, April 19, 2006

Who needs road rules?

There is a theory that if you take away the road rules everyone would have to driver slower and safer to make sure they don't have accidents. There is evidence to back this up. Think about your local street. Imagine kids were frequently playing ball in the road. How fast would you drive? If there was an accident the kid would get hurt, but not killed. Parents are scared their kids will get hurt, so people move off the streets to the front lawn.This gives the cars a chance to go faster, this makes the roads less safe, so the kids are told to only play in the back garden. This means the cars can go even faster. Now if there is an accident it will be fatal. Take a look at this footage from an intersection in india. The cars all keep moving. The speeds are quite slow though. Everyone expects someone to get in their way. No accidents.

There has to be a simpler way!

Tuesday, April 11, 2006

Comments are for 'why?'

I have blogged on this before, but I keep running across it, so here goes again...

Here is a snippet from some VB code I am having to clean up at the moment.

    Public Property PasswordKeyboard() As Boolean
'Retrieves PasswordKeyboard
Get
Return boolPasswordKeyboard
End Get
'Assigns to PasswordKeyboard
Set(ByVal Value As Boolean)
boolPasswordKeyboard = Value
End Set
End Property


Check out the comments! Your code should clearly explain to the reader your understanding of the problem domain, and your solution to the problems involved. Your code should answer a few questions: What is it doing? How is it doing it? and Why is it being done that way?
'What' should be covered by the method and class names.
'How' is covered by the method body (which should be made easy to read)
'Why' is something you can't easly enbed in the code. This is where comments are invaluable. This is what comments are for.

The only reason I can see for having the comments in the above code is to explain why you put the following lines of code in the file. This only make sence if you are trying to document/teach the VB
language. Maybe this is why this problem is so prolific. When someone learns to program they come across this sort of commenting all the time in tutorials. Students duplicate what they are fed, so they add the same comments to their own code.

Do me a favor... if you see this style of commenting anywhere in code you have your hands on, just delete it. The code will be MORE readable, and smaller. Your brain will thank you.


Friday, February 10, 2006

Casting from object[] in C#

Can anyone explane this?
ArrayList list = new ArrayList();
list.Add(new Banana());
object[] areTheseBananas = list.ToArray();
Banana[] bananas = (Banana[]) areTheseBananas; // causes runtime casting exception!
Why doesn't the language allow this?

I know you can do...
ArrayList list = new ArrayList();
list.Add(new Banana());
Banana[] bananas = (Banana[]) list.ToArray(typeof(Banana));
...but in the code I am working with I don't know the type of the array at the point that ToArray is being called.

Thursday, February 09, 2006

Missing method? What missing method?

I just spend the best part of a day tracing down why my unit tests were throwing a 'MissingMethodException' with a description of exactly the menthod that was there. I recompiled, I rebooted, I did everything I could think of. It still didn't find the method. I wrote a simpler test. No good. I ended up with a test that created an instance of the class and called a one line method that just returned a constant int. Still no good.

I explored the assembly that was being created when I compiled with Reflector. Everything was there. All in place. So the assembly was created ok.
So..the hunt was on. What assembly is NUnit picking up?

Eventually.. through the use of fuslogvw.exe and this helpful advice I eventually found it was loading from 'C:\Documents and Settings\nigel\Local Settings\Application Data\assembly\...someplace'. I tried to delete this directory, and couldn't because devenv.exe was using it. So it turns out Dev Studio was helpfully holding onto an old version of an assembly I was working on in a place that .Net checks BEFORE it checks the directory the test assembly was in. How rediculious!

I killed closed dev studio. I killed the devenv process that just kept hanging around even though devstudio was no longer running (nice) and then deleted the '...Application Data\assembly' directory.

This time I run the tests and Ping! lovely green lights.

I mention this so maybe it will save you the 1/2 day it cost me. :)



Monday, February 06, 2006

online calendar with RSS

One of the many projects I have on the back burner (waiting for enthusiasm) is an online calendar/agrigator.

http://www.spongecell.com is a good calendar (with lots of ajax goodness) and a nice simple plain text way of adding appointments.


Friday, January 13, 2006

Capture the path of the executing batchfile

I have a batch file for doing some automated deployment magic. It calls other batch files via relative paths. The problem with this is that it doesn't work if you call the batch file from a different directory.

Once I started looking I came across this litte gem %~dp0.

%0 is the name of the batch file.
~dp gives you the drive and path of the specified argument.

You can then get your batch file to run from its own directory as follows...
pushd %~dp0
... do batch file stuff
popd

Thursday, January 12, 2006

nice css bargraphs

See some nice CSS bar graphs here

Wednesday, January 11, 2006

Tuesday, January 10, 2006

Lego has come of age

Check out the new lego Mindstorm products. Robots that can sence colour, movement, noise, tone, pitch, ultrasound, stepping motors with 360 position sensors... All with bluetooth control.

This is the first time I have felt that I was born a generation too early :) Lego is officially a big boys toy.

Monday, January 09, 2006

Seaside in action

An alternative to the Ruby On Rails framework is a smalltalk framework called Seaside. Seaside has been around for much longer than Rails, but as yet has not experiences the same degree of rapid uptake.

A great example of how powerful this framework can be is a fantastic web app that is currently under development called DabbleDb. The aim of the app is to allow Spread Sheet users to create real db application instead of using Excel. What I like most of all is the way they perform automatic migration of existing data as you change the schema. All this is achieves with a very simple user interface and no need to understand databases. Here is a video of a demo where they create a todo list application in no time flat. I have seen another than has the 'split the name into first and last name' that they mention in this clip.

GitHub Projects