Mark Embling's Blog http://www.markembling.info/ Various technical writings of a .NET and PHP developer in the UK. en-gb Copyright © Mark Embling 2006-2010 60 Roll Your Own...? http://www.markembling.info/blog/view/slug/roll-your-own http://www.markembling.info/blog/view/slug/roll-your-own Thu, 25 Feb 2010 13:31:04 +0000 My blog is not based on Wordpress or Subtext or any of the others. Its something custom which I put together and occasionally add to or modify to suit my needs as they change. However, its written in PHP and as much as I like PHP for inspiring me to get into web development, in my opinion it has gotten a little tired. I intend to patch a few missing-but-essential features into the current version whilst I rewrite it completely based on Rails 3.

However, some would say I'm foolish for taking this route.

I like my blog. I approached the problem my way and on the whole I think it works pretty well for me. It is missing a bunch of features some might consider essential and it certainly has its own little quirks but I like it. It has grown almost organically from my uni days and has gradually changed its focus from being focused on showcasing me as a potential employee (no blogging features way back) to a site which is becoming more personal and focused on my life as a developer. However as a result of this shift, it has become lacking. It currently has no support for trackbacks/pingbacks or any of the APIs like the MetaWeblog API. Trackbacks/pingbacks are something I really need now in order for it to function effectively as a coherant member of the blogosphere - I'm sure my meagre visitor stats are in part down to this oversight.

Some people think I am making life hard for myself with having to implement all these various features, and that I would be better off simply switching to Wordpress or one of the other blogging engines. I can't disagree - Wordpress is definitely good at what it does. But it's not mine.

I think that Rob Conery nailed it when he wrote about his reasons for writing his own blog:

  1. It’s the perfect app for a geek who wants a blog to build – they’re the perfect domain experts
  2. It’s easy (for the most part) but gets harder and harder the farther in your dive
  3. It’s ubiquitous. What a perfect interview topic: “I’d love to see how you handled asynchronous pings to Technorati and – oh – do you have a POP feature? Also – did you use MetaWeblog or Wordpress?”
  4. It’s your calling card. If your blog rocks – likely you do too. If it sucks and it’s slow – well…
  5. It’s a great way to learn a language. Want to try out ASP.NET MVC? Compare the LOC and features to your Webforms blog – then try Rails…

Writing your own blog allows you to customise the behaviour completely. It is a lot more work for sure, but at the end of it you get something which you created and can be proud of. Something a bit more personal than just another Wordpress blog. Don't get me wrong though, I am not bashing the use of pre-existing blog engines. I know I have reinvented the wheel - Rob did too. But to be honest, I don't really care. This way allows me to take nothing and craft it into something. And somehow it means more for someone to say nice things about something you created yourself than if you just ran an installer and customised a theme.

That is why I won't move to Wordpress and will willingly spend time building my own version. Because I can. Plus I know it sounds a bit illogical, but it means more to me than just a bunch of source code or just another project. I would not presume to tell anyone else they should do the same, but I felt it was worth explaining the reasoning behind my choice.

]]>
Drobo & DroboShare http://www.markembling.info/blog/view/slug/drobo-and-droboshare http://www.markembling.info/blog/view/slug/drobo-and-droboshare Mon, 22 Feb 2010 13:00:47 +0000 Recently I bought a Drobo, a storage device which takes up to four SATA hard drives and combines them together to form a large volume whilst at the same time providing protection against drive failure or corruption.

Drobo comes with the ability to connect locally like any other storage device via USB or Firewire 800. It is also possible to connect it to your network using a DroboShare. I chose this option and bought the Drobo and DroboShare bundle from Ebuyer.

First Impressions

As I was unboxing the Drobo and DroboShare, the first thing which struck me was the quality of the packaging. Both the Drobo and DroboShare came in their own boxes with well put together inner sections. The devices themselves were carefully wrapped in cloth covers. Unfortunately I did not take any pictures of the unboxing process.

As I got the devices out, it became apparent that the solid well-put-together feel of the packaging extends to the units themselves. It seems the Drobo is solidly put together out of good quality materials. Its worth noting that the glossy front panel does seem somewhat prone to attracting dust though. In addition, the device seems longer in real life than it looks in picture, although not unreasonably so.

As well as the devices themselves, the boxes contained easy setup instructions, a full manual, the device software (Drobo Dashboard), all the necessary cables and the usual warranty documents.

Setting Up

Setting up the Drobo and DroboShare was easy. It was simply a case of placing the DroboShare down and hooking it up to the network and plugging in the short USB cable it was provided with. The Drobo device could then be placed on top and the other end of the USB cable connected to the USB socket on the back. I also took this opportunity to plug in a 500GB and a 250GB hard drive, leaving two drive bays available for expansion. Finally, I just had to connect the power cable to the mains and plug it into the supplied Y-splitter, which was connected to both the Drobo and the DroboShare. It then began it's first power-up.

The next step was to initialize (format) the Drobo. This only needs to be done once, and it tells Drobo what volume size to use. Being a typical male geek, this confused me for a moment since I hadn't read any of the documentation, but it turns out that Drobo pre-formats itself with a given volume size (which you can choose) regardless of the current capacity of the drives. The default volume size is 2TB, but you can select from between 1TB and 16TB. I chose 4TB (the larger the size, the longer the boot time). What this means is that I can continue to add and replace hard drives with larger ones as I see fit, but if the capacity grows to the point where the available space (after protection) goes over 4TB, Drobo will automatically add a second volume. Since I'm sharing my Drobo using the DroboShare, each volume appears as a network share.

It is well worth noting that since the volume size is set to a maximum of 4TB, my computers see it as that size (not its "actual" size). This could be confusing if you often rely on Windows or OS X to tell you how much free space you have left, as it will most likely not match reality. However the Drobo guys provide Drobo Dashboard, which does report the correct free space and the Drobo itself has a row of blue LEDs along the bottom which give an at-a-glance view of space used.

Using Drobo & DroboShare

Using the Drobo (with DroboShare) is just like using any shared volume. Simply find it on your network and copy files to it, read files from it and use it as you normally would. You will notice above that during the setup procedure all I had to do was install Drobo Dashboard and it all automatically worked. It automatically detected the devices on the network (since it'd picked up an IP via DHCP). Using Drobo Dashboard you can assign it a static IP and change its name and the volume names to whatever you prefer.

The reason I bought the Drobo was to take three hard drives I had sat in a spare computer full of movies, music and other data. Up until now I had to turn that machine on every time I needed to get to it and it was really beginning to become annoying. Having it always accessible over the network is much more convenient. However, this presented an interesting challenge.

Drobo & Capacity

The Drobo automatically allocates space for data and space for protection of that data across however many drives are installed. This means that the data is always protected against failure of a drive if there are two or more installed. Imagine RAID which automatically adapts to the number of drives without the need to reformat or rebuild and you are pretty much there. However, it turned out that Drobo does need at least two hard drives at whatever size your largest hard drive is in order to not waste space.

This turned out to be a bit of a problem for me. As I mentioned before, my data was split across 3 drives: 250GB + 500GB + 500GB. I had moved it all from two of these (the 250GB and one of the 500GBs) onto just the other 500GB and a space 250GB external drive, allowing me to take one 250GB and one 500GB drive to put into the Drobo. I then began the very lengthly task of copying all my data (near enough 600GB) from the machine to the Drobo.

500GB + 250GB + 500GB = 1.3TB (1.1TB actual), 231GB available for data, 231GB reserved for expansion

You'll remember I said that if you put one large and one small drive in, there is some wasted space. The diagram above shows this - the purple portion is not available. There was not nearly enough space for all my data, not even the data from the 500GB drive only. My original plan was to copy the data from this drive over, then take the drive out of the computer and put it into the Drobo in order to then copy the data from the external drive over. This clearly wasn't going to happen after all, and I'd already started the copying process. This presented a bit of a problem: I had no other spare drives. Since the copy was still taking place and I had no wish to stop it (and no other plan of action even if I did), I decided the only thing I could do was an emergency trip to PC World for another drive. Thankfully it was only 19:40 so they were open for another 20 minutes. Having returned with another 500GB drive (and £54.99 lighter - thanks PC World), I could stick the new drive in providing enough space.

Here is the beauty of Drobo. You can stick in new drives and even pull one out while it is running. Not only is it hot-swappable, it doesn't miss a beat. I put the new drive in and within seconds it had recalculated the space available to account for the new drive's presence, all the while still copying over my data. Which could now fit thankfully.

500GB + 250GB + 500GB = 1.3TB (1.1TB actual), 696GB available for data

It is well worth bearing this little quirk in mind when buying a Drobo to ensure you don't force yourself into an emergency drive buying trip like I did. You can use the Drobo Calculator to find out what would result from your chosen combination. The blue "available for data" section is the actual usable space you get. The grey "used for protection" section is the space used to ensure you are protected against drive failure. Ideally you don't want any of the purple "reserved for expansion" showing as this is effectively wasted space.

Final Thoughts

It is worth remembering that the Drobo is fully automated. This means it will sometimes spin up randomly for apparently no reason in order to do maintenance to itself (defragging and so on). For this reason, you may not want to put it in your living room or bedroom if you object to the sound of a fan and hard drives spinning up. It is not loud, but the noise level does exceed that of the average desktop computer fan occasionally.

Another point worth making is that the Drobo Dashboard software is not required - you can use the Drobo like any network share from any machine. However it does seem to be required for setting it up and I would recommend installing it on your main machine so you can keep tabs on storage space and make changes to settings if necessary from there. I have it installed on my iMac, and both Windows and OS X versions are provided (but no Linux unfortunately).

Overall, I very much like the Drobo. It takes the idea of redundant storage and makes it painless and easy. All you need to bring to the table is a bunch of standard 3.5" SATA hard drives and it will do the rest.

My final configuration contains three 500GB drives (bays 1, 3 and 4) and one 250GB drive (in bay 2).

Screenshot of Drobo Dashboard

Photo of my Drobo and DroboShare

This provides me with just over 1.1TB of storage space, all completely protected against drive failure. And if a drive failure does occur, one of the lights on the front of the Drobo will turn red to alert me and I will simply pop it out and push in a new one. Drobo does the rest.

Would I recommend it? Yes, definitely.

]]>
Backups Are Not Optional http://www.markembling.info/blog/view/slug/backups-are-not-optional http://www.markembling.info/blog/view/slug/backups-are-not-optional Wed, 10 Feb 2010 13:26:57 +0000 Last night I was given a sharp reminder that having a backup strategy for any content you value is important. I know it has been said many times before and will continue to be said many more times in the future but even if you don't read any further, just do yourself one favour: make sure your backup strategy is in place and is working.

So Why The Lecture?

You know how it is... you have a VPS or a dedicated server running your blog and a few other sites. You have the important configuration files and so forth backed up and the standard snapshots provided by your ISP, but no proper backup strategy for your content.

It is just sitting there in your database, growing slowly. Watching. Waiting. One day when you aren't looking, disaster will strike.

Or maybe you'll be lucky. I was.

Somehow my VPS managed to get well and truly broken. I'm not completely sure what caused it (it could have been one of several things) but the end result was the Plesk config was ruined and totally useless. Normally I wouldn't see the need for Plesk as I'd just set everything up myself, but I have some friends' sites as well and its nice to be able to provide them the ability to log on to their own control panel to manage their services. Unfortunately, I had no way to revert or undo what had happened so I had to resort to using one of the automated image backups provided by the ISP. This backup was dated 1 Feb – 9 days ago. Not ideal...

I applied the backup and once restoration was complete, sure enough everything came back happy and working again. But horror of horrors - my last blog post was missing. And I had no backups of this at all.

Message Received & Understood

One blog post... that's all I'd lost. And I've even got that back thanks to Google's cache. All is restored, and it only took 5 minutes to do. But the message is clear: next time it could be much worse.

I will be making sure I have some kind of proper strategy in place in the future to back up my blog (and other) content. As a developer I really should have known better in the first place, especially reading about the horrible losses others have suffered in the past.

So if you think your stuff could go the same way, check. Set something up. Even just a simple script will do. Next time it could be you. If your data is important to you (or to others), backups are not optional.

]]>
DeveloperDeveloperDeveloper 8 http://www.markembling.info/blog/view/slug/ddd8 http://www.markembling.info/blog/view/slug/ddd8 Mon, 01 Feb 2010 12:41:00 +0000 Like many other developers from around the UK, I was at Microsoft's Reading campus on Saturday for DDD8. I have already had the chance to read several blog posts reflecting on the day and I echo the sentiments - it was (as always) a positive experience with interesting talks and the chance to meet people in real life and put a face to a (twitter) name.

Before the Day

Registration opened a couple of weeks before the event (on January 15th if I remember correctly) and all the spaces were taken within about 12 minutes. I believe this is a record for any DDD event so far. Thankfully I was one of the lucky ones who managed to get a space, despite the problems affecting the registration system which made it impossible to tell at first. All credit goes out to the organisers who did their very best and have already said the registration system is going to be addressed in the future, so I will say nothing else negative about this minor pain-point, but instead thank them for working so hard on setting up this event for us all.

Talks

As always, choosing which talks to go to was not easy. All of the talks sounded good, but in the end I picked the following ones to attend:

  • Ian Cooper - Real World MVC Architectures
  • Neil Robbins - Hello Document Databases
  • Jon Skeet - C# 4
  • Gary Short - Not Everything is an Object
  • Barry Dorrans - A developer's guide to encryption

The first session of the day for me was Ian Cooper's talk about real world MVC. He covered various anti-patterns which he'd run into such as the "fat controller" and leakage of logic from one layer into the other. He also covered the need for a service layer in larger systems. A lot of what Ian covered were issues which we've run into at work ourselves, so it was good to hear how others have gone about handing the same sort of scenario, and the best-practices which have come out of it.

The second session I attended was Neil Robbins' talk on document databases. This was a session I was very much looking forward to as the "NoSQL" movement and document databases in general are an area I've become interested in lately. Neil focused on CouchDB, which was also interesting because I have looked mainly at MongoDB. It was interesting to see how they have both addressed the problem in different ways. It was also nice to see Ubuntu CDs being handed out at Microsoft. All in all, I very much enjoyed this session and it has prompted me to take a closer look at CouchDB as well as continuing my MongoDB explorations.

After a break, Jon Skeet was up talking about changes and new features in C# 4. This was a very popular talk, proven by the fact they had to open up Chicago 1 & 2 into one large room and still it was full. This was my first Jon Skeet talk experience and it did not disappoint. Jon covered optional parameters, generic variance (which I still found confusing despite his very good fruit-bowl/banana explanation) and a lot more. He was also the only person I've ever seen to use images as slides.

After lunch (the traditional brown-bag type kindly provided by Microsoft), I attended Gary Short's session entitled "Not Everything is an Object". He covered why the OO paradigm might not be the most suitable for all problems going forward and the benefits which can be found in a functional approach. He illustrated all this using Clojure, a functional language based on the JVM. This is something quite new (and more than a little alien) to me and well worth taking the time to look at once I can spare some.

The final session of the day for me was Barry Dorrans' session on encryption for .NET. This was Barry's last DDD talk before he departs for the US and a new job at Microsoft (a fact which was pressed home throughout by various fun pranks played on him). As always, it was a good talk and covered many different aspects of encryption and hashing, and illustrated them through demo code which we saw running.

Conclusion

I think most attendees will agree with me that DD8 was a great success and well worth the trip. I got a lot out of the day, from the great sessions and from the ability to meet and talk with other like-minded devs from around the UK, and put a real face to some twitter names (and meet a few more besides).

I'd like to thank all the speakers who's session I attended for giving their time and knowledge freely. I'd also like to thank the organisers and everyone else involved in making the day happen. Events like this are invaluable for bringing developers together and enabling the sharing of knowledge.

Now it's time to look forward to WebDD and DDD9.

]]>
DevEvening - Introduction to Git & PowerShell http://www.markembling.info/blog/view/slug/devevening-talk-git-powershell http://www.markembling.info/blog/view/slug/devevening-talk-git-powershell Fri, 29 Jan 2010 14:04:26 +0000 Last night at DevEvening I did my first user group talk: an introduction to Git and PowerShell. As promised at the time, I have collected together some relevant links and made my slides available to download.

DevEvening Overall, I think the talk went alright. Since it was my first one I am certain there are improvements I could make in the future, but hopefully I got across the potential advantages of the tools I like to use and whetted people's appetites for what could be done with them and their potential applications.

Links & Downloads

In addition to the command line tools and TortoiseGit, several people seemed interested in having a Visual Studio add-in for using Git. As I said at the time, I generally prefer to use the command line and therefore couldn't really give a good answer as to whether such a thing existed. However, I did a quick google search and it would appear that there is such a thing - Git Extensions seems to be another Windows Explorer integrating add-in (along similar lines as TortoiseGit I would guess) but which also comes with a Visual Studio add-in. Needless to say, I haven't tried it myself so can't comment on how good it is, but there have been several positive comments about it so it may well be worth a look.

Once again, thanks to everyone who came along and listened to me and asked questions, and to Matt Lacey for running the event every month. If anyone has any comments on the talk, feel free to comment or tweet me.

]]>
Git Environment on Windows http://www.markembling.info/blog/view/slug/git-environment-windows http://www.markembling.info/blog/view/slug/git-environment-windows Fri, 22 Jan 2010 16:27:24 +0000 It is probably evident from previous posts on my blog that I like Git and working with it from within PowerShell. In the past I have talked about tweaking the PowerShell prompt to add git stats and setting up SSH-agent to work from PowerShell, however I have never actually gone through my entire Git/Windows environment and the steps taken in order to set it up. I thought it was time I did.

Ingredients

Like most Windows Git users, I use the excellent MSysGit. This provides us with all the Git, SSH and Bash binaries, packaged up in a nice friendly installer. Rather than sticking with the MSysGit-provided Bash shell however, I use PowerShell. If you are using any modern version of Windows this will be installed already. It can also be added for those people who are stuck with (or still prefer) Windows XP (link).

In addition to these basic tools, I use the following:

  • Console – excellent terminal application with multiple tabs and customization options
  • DiffMerge – pretty decent diff/merge application
  • Notepad++ – great text editor with tabs, syntax highlighting and no nonsense

Installing & Setting Up Git

Installing MSysGit is simply a case of running the installer. However it is well worth remembering to choose one of the two options which allows use of the Git commands from the Windows command line (and by extension, PowerShell), otherwise you will be limited to using Git from inside the Bash shell it installs (making this entire guide a bit pointless). I normally use the last option and have found it has no ill effects for my uses.

The next two steps ask you which SSH client you'd like to use and which style of line endings to use. I always select OpenSSH and recommend doing the same unless there's a particular need not to. I always set line endings to use Windows (since I'm almost always working with Windows-centric projects when I'm working from Windows), but feel free to select whichever setting will work best for you.

First of all, you should tell Git who you are. Fire up a PowerShell instance and run the following commands (substituting your name & email for mine of course).

git config --global user.name "Mark Embling"
git config --global user.email "no-spam-please@markembling.info"

Assuming this completed without issues, Git should be ready to use. Feel free to set up or clone your repositories now or later. Git will use the user information you have given it on all your future commits.

Notepad++ and Git

Installing Notepad++ is again a case of just running the installer. Git can be made to use Notepad++ for all its editing (commit messages for example) using the following command (substituting the path as appropriate).

git config --global core.editor "'C:/Program Files (x86)/Notepad++/notepad++.exe' -multiInst -notabbar -nosession -noPlugin"

The various flags tell Notepad++ not to display the tab bar, load plugins and a couple of other appropriate settings. Note the position of the single and the double quotes - I've been caught out by missing them out in the past.

Setting Up DiffMerge

Sometimes during development it is inevitable that you will encounter conflicts where you have modified a given section of a file and someone else you are working with has made a different change to that same file. Although Git has some pretty good smarts when it comes to merges, sometimes it will be impossible for it to resolve automatically. When this happens, there is nothing worse than having no decent merge tool. Sometimes you just want to see what changes you've made - again, having a decent tool helps immensely here. DiffMerge serves both of these purposes well, and can be tied in to Git so that you can call up a diff or a merge when necessary with a single command.

Once again, installation is a simple installer. Once it is installed, it needs to be hooked up to Git. You will need two small scripts, mine are below (again, change the paths as appropriate). I have placed these in C:\Program Files (x86)\git\etc\wrappers, but you can place then wherever suits you best.

git-diff-diffmerge-wrapper.sh:

#!/bin/sh
"C:/Program Files (x86)/SourceGear/DiffMerge/DiffMerge.exe" "$1" "$2"

git-merge-diffmerge-wrapper.sh:

#!/bin/sh
"C:/Program Files (x86)/SourceGear/DiffMerge/DiffMerge.exe" "$1" "$2" "$3" --result="$4" --title1="Mine" --title2="Merging to: $4" --title3="Theirs"

Having created these wrapper scripts, they can be hooked up to Git inside your Git config file found at C:\Users\<You>\.gitconfig (or C:\Program Files (x86)\Git\etc\gitconfig to affect all users). Add the following sections to the bottom of the file:

[diff]
    tool = diffmerge
[difftool "diffmerge"]
    cmd = 'C:/Program Files (x86)/Git/etc/wrappers/git-diff-diffmerge-wrapper.sh' "$LOCAL" "$REMOTE"

[merge]
    tool = diffmerge
[mergetool "diffmerge"]
    cmd = 'C:/Program Files (x86)/Git/etc/wrappers/git-merge-diffmerge-wrapper.sh' "$PWD/$LOCAL" "$PWD/$BASE" "$PWD/$REMOTE" "$PWD/$MERGED" 
    trustExitCode = false
    keepBackup = false

Now that DiffMerge is hooked up to Git, you will be able to use git difftool and git mergetool at the command line to open it up. For example, if you have made changes to a file which you have not yet staged for commit, git difftool (for all changed files – it will open them one after another) or git difftool <filename> (if there's a particular file you want to know about) will allow you to compare your changes with how it previously looked. It can be quite useful to recap what changes you've made prior to a commit. Using the git diff and git merge commands will still fire up the built-in (and quite frankly terrible) tools.

Setting Up Console

Installing Console is simply a case of downloading the binaries and copying them to a convenient location. The program's settings are stored alongside it so it is easily carried from one machine to another if necessary.

The default settings for Console have it set up to use Command.exe. I normally set up a new tab (Edit → Settings) which uses PowerShell and set it as the default tab type by moving it to the top of the list. The path to the PowerShell executable is generally something like C:\Windows\System32\WindowsPowerShell\v1.0\powershell.exe. Settings like the background colour, tab icon, cursor appearance and more can also be tweaked to your liking.

PowerShell Extras

Whenever I set up a new Windows environment, as well as installing everything I've written about here I always change my PowerShell prompt to give me Git information whenever I'm within a Git repository. As I touched on in the introduction, I have written about it and provide the scripts which can be integrated into your PowerShell profile.

In addition to this, I also use another script which integrates SSH agent into the PowerShell environment. This is something else I've written about. Note that this relies on the ability to run the ssh-agent binary, so this needs to be located somewhere in the PATH.

Feel free to use these as you wish, I find it makes the whole Git/PowerShell experience feel that bit more efficient and polished.

More Resources

Jeremy Skinner has written a great guide to getting started with Git. It is written focusing on GitHub and the MvcContrib project, but is relevant to Windows Git users generally. It's worth noting he makes a couple of slightly different choices to me regarding his setup, so my best advice would be to pick whichever fits your environment and workflow best.

A couple of other resources worth checking out:

]]>
Going 'NoSQL' with MongoDB and C# http://www.markembling.info/blog/view/slug/mongodb-and-csharp http://www.markembling.info/blog/view/slug/mongodb-and-csharp Mon, 14 Dec 2009 15:39:09 +0000 I've noticed with interest the 'NoSQL' movement which seems to have arrived recently and have on the whole ignored it. I generally find myself getting on well with relational databases and based on that fact (and the fact they are so commonly used), I have not looked into any of the alternatives. However, I have recently read various articles talking in particularly about CouchDB and MongoDB and after reading a little bit about both, I decided to give MongoDB a closer look.

What Is MongoDB?

MongoDB is a fast and lightweight schema-less document-oriented database. Essentially, rather than having a database with tables consisting of a number of rows, you have a database with a set of collections. Each collection holds a number of documents. Now I know what you're thinking – it sounds like exactly the same thing but using different terminology. I guess it can be thought of like that but the big difference is the 'schema-less' aspect. Not all the documents in a given collection have to be structured the same way. In fact, its quite possible to store completely different documents in the same collection. In practice, I imagine its more likely that you'd probably keep the same or similar items in a collection, but it certainly provides more flexibility should it be needed. It could also be useful in the case where you are storing an object hierarchy and the documents share some common fields but not all.

MongoDB also allows each document to have "sub-documents". For example, its possible for a Person document to have an Address sub-document (with all the appropriate fields like city, postal code etc on it). Sometimes this might make more sense than the traditional relational model where you have your people in the People table and the addresses in the Addresses table.

This has only scratched the surface of what MongoDB can really do. I would recommend taking a look at Wynn Netherland's slides on the subject (ruby-oriented but a great intro to MongoDB) and some of the articles linked from the MongoDB site.

How Do I Use IT?

There are official MongoDB drivers for lots of languages and platforms such as Ruby, PHP and Python, along with several community-maintained ones for other languages. The MongoDB site holds a pretty comprehensive list. It is one of the community-maintained ones which I have used to connect and make use of MongoDB from .NET: MongoDB-CSharp.

Scott Allen has written a great post on using MongoDB-CSharp, and this has been followed up by another great post by Hernan Garcia, where he abstracts the MongoDB stuff behind a nicer model layer which he can then work with from within his app.

My app did not use this technique, rather it is right down-to-the-metal MongoDB Document all the way. Not the sort of thing you'd want in a production app, but my aim was to have something simple and basic working. I also do not like the way Hernan's domain entities have to know so much about how MongoDB works either – something I will try to look at and write a follow-up post on I think.

MongoDbNotes Project

I've babbled on for long enough, lets get to some code. My application is a small ASP.NET MVC 2 app which allows the user to add simple post-it style notes (with a title and a body) to the site, tag them, and delete them. At the moment it's missing any other functionality (like editing), but you get the idea.

Unlike the approach Hernan uses, I am connecting to the database right upfront during the Application_Start and storing it for use throughout the app in my IoC container (Autofac in this case).

public static MongoDB.Driver.Database ConnectMongoDb() {
    var host = ConfigurationManager.AppSettings["mongo-host"];
    var port = int.Parse(ConfigurationManager.AppSettings["mongo-port"]);
    /* username, password and database too */

    var mongo = new Mongo(host, port);
    mongo.Connect();
    var db = mongo.getDB(dbname);

    if (! string.IsNullOrEmpty(username)) {
        db.Authenticate(username, password);
    }

    return db;
}

The MongoDB.Driver.Database instance here is then injected into my repository implementation (NoteRepository) when it is needed, where it can be queried and inserted into. It is in this repository where I have placed all the logic for querying, saving and deleting entities.

Scott Allen's post talks about querying the database by passing it an example of what you would like (he uses movies). I have made use of this to create a FindById method. It takes an Oid instance and then returns the document which has this ID in its _id field. It is worth noting that all documents inserted into MongoDB have an _id field automatically added. You can think of it a bit like an auto-incrementing ID from MySQL or the like, but it is generally not an integer (rather its a collection of bytes generally represented as a hex string). I make use of this for specifying deletion criteria as well.

Another thing worth mentioning is MongoDB's concept of an 'upsert'. This is an insert or an update – whichever is appropriate. If the item you are attempting to add does not yet exist, it is an insert and if it does, it is an update. MongoDB-CSharp provides access to this facility through the Collection.Update method by taking an additional parameter in one of its overloads. Not too sure why it's an integer rather than a boolean but still, it works.

MongoNotesDb screenshots

Get The Code

The MongoDbNotes app lives in my experimental repository on GitHub. You can get the latest version by cloning it or asking GitHub for a download. I'm sure there's a fair amount of improvement which can be done to the app (editing would probably be good) so feel free to have a play. Don't forget to grab yourself the latest stable MongoDB version first too – it runs on Windows, OS X and Linux.

Conclusions

I like MongoDB. I like it enough to make the decision for it to power the next version of this site (which will be Rails-powered too). However I do think that it is still very young, particularly in relation to .NET. I think that within the Ruby community it has gained a fair bit of traction and therefore has more open-source solutions centring around it but in terms of .NET, it still has a long way to go – the fact that at present you have to work bare-metal with Documents and things or effectively roll your own O/R mapping layer proves that. But don't let this stop you giving it a test-drive.

]]>
Better CSS with .Less http://www.markembling.info/blog/view/slug/better-css-with-dotless http://www.markembling.info/blog/view/slug/better-css-with-dotless Fri, 27 Nov 2009 13:11:21 +0000 Too often in my web development past I have found myself wading through huge clumsy CSS files of several hundred lines or more, searching for that place where a particular class is defined or to try and identify what it is that is overriding something else. It can be quite a nightmare. However I recently came accross .Less (pronounced "dot-less"), a port of the great Ruby Less library for .NET. This is a brilliantly simple-to-use solution to an often-painful situation.

What Does It Do?

Less gives us CSS-but-better. It takes the standard CSS syntax we all know and adds nesting, variables, mixins and operations. No longer must we violate DRY by copying colours and sizes around throughout the stylesheet or defining and redefining the same inheritance hierarchy.

Using variables, it is possible to define some often-used values throughout your stylesheet (website/company colours for example) and refer to them at various points.

@background_color: #b6e2f8;
@foreground_color: #0a5389;

body {
    background-color: @background_color;
    color: @foreground_color;
}

Using operations, it is possible to define relationships between different values throughout the stylesheet. This is something I've found particularly useful for defining color variations for hovered/focused links, as in this example.

@link_color: #234206;

a {
    color: @link_color;
}
a:hover, a:focus {
    color: @link_color + #141414; /* brighten when hovered */
}

This sort of operation can work on all units, so can affect font size, border widths, colors and whatever else you need to adjust in code. So far, I have only used it for a few things such as highlight/hover colours like my previous example.

Less also allows us to use nesting as you would expect, in place (or alongside) standard CSS cascading. The following two examples would therefore be equivalent.

Less:

.sidebar {
    background-color: @sidebar_bg_color;
    border: solid 1px @sidebar_border_color;
    padding: 0.2em;

    a {
        color: #234206;
    }
}

Plain CSS:

.sidebar {
    background-color: @sidebar_bg_color;
    border: solid 1px @sidebar_border_color;
    padding: 0.2em;
}

.sidebar a {
    color: #234206;
}

Of course, this is only a very simple example. I have found that scaling it up to an entire site gives CSS a much more natural feel and I am actually more productive using it despite having used 'plain' CSS for quite a few years now.

Mixins, as I mentioned at the top of the post, are also provided as well. Basically these take the form of standard CSS classes which you can then use to help build up more complex sets of rules.

.zero_margin_padding {
    margin: 0;
    padding: 0;
}

.sidebar pre {
    .zero_margin_padding;
    /* More styles here */
}

In addition to simple cases like the one above (something I often find myself doing, now with much less repetition), it has been pointed out that this is particularly useful when combined with a CSS framework. I am not one for using these frameworks, but I can certainly see how the two would work very well together.

My Thoughts

I have only briefly run through the features of Less but I think it is safe to say I very much enjoy the power it brings to CSS, all without introducing a whole new syntax or anything particularly unexpected. Now that the .Less guys have created a .NET port of the original Ruby version, we can enjoy Less in both the Ruby and .NET environments. And that can only be a good thing.

There is an alternative in the form of Sass which may also be worth a look, although it is (at present at least) a Ruby-only solution. It adds pretty much all the same features but eschews CSS syntax for a bracket-free syntax, using indentation as the block delimiter. My personal choice is for Less due to the fact that it keeps all the original CSS syntax and just adds new capabilities, but there's no denying the fact both are good and both appear to serve their purpose well.

More information and in depth examples can be found at the Less documentation. I also found Chris Owen's thoughts and insights well worth the read. In addition – particularly for those who want to dive into using .Less in their .NET apps now – check out how easy it is to install. The instructions are right there in the .Less website's sidebar.

]]>
Phantom Build System Additions http://www.markembling.info/blog/view/slug/phantom-build-system-additions http://www.markembling.info/blog/view/slug/phantom-build-system-additions Mon, 02 Nov 2009 09:36:57 +0000 Not long ago Jeremy Skinner created Phantom, a build system for .NET based on the Boo language. Since its creation, I have been following it with interest (and have forked it).

Up until recently despite my interest, I had not had the opportunity or reason to make any modifications to it. However, I have not long started developing a new site and I thought this was the perfect time to make use of it - it is clear that the clean Python-like Boo syntax is far more preferable than XML-based build files. However, it was missing a couple of features I wanted, so I have added them. I thought I'd briefly document them in this post for whoever might find it of interest.

Stop on Error for 'Exec'

Originally, Phantom had one major shortcoming which made it slightly impractical for anything other than really simple scenarios - if an external tool - be it nant or whatever else run through exec - exited with a non-zero exit code, Phantom would happily continue on to the rest of the tasks in the script. What this meant in real life for me is that even when a build error occured, it still went ahead and ran the unit tests and so on. That clearly would not do.

The solution was of course to check the exit code, and bail out of the build process if it was non-zero. This is fine for many (probably most) cases. However, there are stubborn tools out there which insist on returning non-zero codes for perfectly valid reasons - reasons which should not stop the build. To get around this problem, it is now possible to call exec with an option given in the options hash to allow continuing on non-zero exit codes.

Execute external command and fail on non-zero exit code:

exec("whatever.exe", "--args:here")

Execute external command and ignore non-zero exit code:

exec("whatever.exe", "--args:here", { @IgnoreNonZeroExitCode: true })

NUnit Include/Exclude Categories

This is another small tweak to one of the built-in functions. It is possible to run your NUnit tests using the nunit function within your boo script. However, it did not have any method of specifying which categories of test should or should not be run. I have added this feature and it may be used as demonstrated here:

desc "Runs all the tests"
target test, (compile,):
    nunit(test_assembly)
desc "Runs database tests only"
target database_tests, (compile):
    nunit(test_assembly, {@include: "Database"})
desc "Runs all tests excluding database tests"
target database_tests, (compile):
    nunit(test_assembly, {@exclude: "Database"})

Note that include and exclude are mutually exclusive and cannot be used together. For more information, see the NUnit documentation.

Give it a go

If you are looking for a build system which does away with the XML files of nant and so on, take a look at Phantom and see what you think.


Update (2 Jan 2010)

Since writing this, Phantom has been developed further and some changes have occured affecting the contents of this post. Please see Jeremy's blog entry and the Phantom documentation for full details.

]]>
XML CVs - Why So Hard? http://www.markembling.info/blog/view/slug/xml-cvs-why-so-hard http://www.markembling.info/blog/view/slug/xml-cvs-why-so-hard Fri, 16 Oct 2009 08:38:53 +0100 Recently I've been researching various XML-based standards and formats for storing a CV. It seems that various different people and organisations have taken a bash at solving the problem, but there is no clear winner or format of choice. It seems to me there is a lot of confusion and quite a few half-baked solutions aimed at the problem - it is clearly something people other than myself have looked at, but that's about all I can say.

What's the Problem?

I have decided to rebuild this site in Rails to replace the current PHP-based site. I'm doing this for several reasons - to better learn the Ruby language, learn the Rails framework, and just because I can. As part of this, I am looking at all parts of the site and considering how I could do it better.

Currently my CV page is pulled from a custom XML dialect I came up as part of an assignment at uni. However, this was designed around my own Microsoft Word based CV at the time with little or no thought as to future changes which may be required or what other people would need for their own CVs. This makes it a fairly useless format other than for my own small purpose.

It seemed to me that the best course of action would be to identify a preferred XML format for CVs (and résumés) – because let's face it, such a thing must exist, right? Er... no.

The Options

I came across several different options for creating an XML-based CV:

  • XML Résumé Library - This looked promising but it looks like that the project was abandoned at some point around 2004 or so. Seems a shame because it appeared to be gaining traction.
  • HR-XML - Again, this looked promising. Various resources I found on the net had used HR-XML 2.5 for their résumés. Now that the 3.0 version of their standard is released however, they have decided to drop support for the résumé part of the spec and rather focus on other more business-centric areas of HR. Version 2.5 is still supported they say, but why create a new solution for an old standard?
  • cv-xml - This project looks like it started out with the same goals I have in mind, but died quickly...
  • xmlcv - ...as did this, which seems to have died before anything even came of it.

Its quite possible there are more out there, but if I didn't find it, chances are its so little-known that it doesn't matter – after all, will anyone else find it? What does surprise me is that there is nothing which really solves this problem - the most promising (in my opinion), XML résumé library, appeared to never catch on. Are there just too few people who want, need or care about a solution such as this?

So What Now?

All of these abandoned projects and lack of consensus has kind of put me off the original idea. I still think its a good thing and if it ever happens, I'll be happy to jump on board. But for now, I think I'm going to take my ideas (and implementations of them) in a slightly different direction.

I'm sure I will follow this up in due course with whatever I come up with.

]]>