Wednesday, February 1, 2012

Exploring TodoMVC and knockout.js with unobtrusive bindings

There’s an interesting project I’ve been keeping an eye on over at github called TodoMVC“a project which offers the same Todo application implemented using MVC concepts in most of the popular JavaScript MV* frameworks of today”.

I’m also a bit of a sucker for knockout.js which aims to “simplify dynamic JavaScript UIs by applying the Model-View-ViewModel(MVVM) pattern”. I haven’t used MVVM extensively before, having only dabbled in WPF/Silverlight, so I’m coming at knockout.js without any preconceived notions of any sort. Plus it has great documentation and examples…

To begin with, I thought I would create a JSFiddle based directly on the knockout.js version of TodoMVC. Really very easy to setup, but nice to be able to play around with.

One of the main complaints levelled at knockout.js is the apparent lack of Separation of Concerns regarding how bindings are managed via data-bind attributes, e.g.

1 <p>First name: <input data-bind="value: firstName" /></p>

This didn’t particularly bother me at first but when dealing with lots of elements/attributes it starts to get more difficult to manage the bindings in the html itself. Turns out knockout.js 1.3+ supports custom binding providers that allow us to refactor the above code into something like (example code only):

1 <p>First name: <input data-class="firstName" /></p> 2 3 <script type="text/javascript" > 4 var viewModel = {name: "Ichigo"}; 5 var bindings = {firstName: {value: viewModel.name} }; 6 ko.bindingProvider.instance = new ko.customBindingProvider(bindings); 7 ko.applyBindings(viewModel); 8 </script>

It might seem like a bit more work to begin with, but now we have true separation between our model and our UI. It also allows much greater flexibility when dealing with complicated UIs.

With this information in hand I’ve decided to port the knockout.js version of TodoMVC to use unobtrusive bindings. There’s surprisingly little work in the conversion process, it mostly involves just pulling all the data-bind attributes out the html and replacing them with data-class attributes that correspond to the properties of the bindings object. 

1 var bindings = { 2 3 newTodo: { 4 value: viewModel.current, 5 valueUpdate: 'afterkeydown', 6 enterKey: viewModel.add 7 }, 8 taskTooltip : { visible: viewModel.showTooltip }, 9 checkAllContainer : {visible: viewModel.todos().length }, 10 checkAll: {checked: viewModel.allCompleted }, 11 12 todos: {foreach: viewModel.todos }, 13 todoListItem: function() { return { css: { editing: this.editing } }; }, 14 todoListItemWrapper: function() { return { css: { done: this.done } }; }, 15 todoCheckBox: function() {return { checked: this.done }; }, 16 todoContent: function() { return { 17 text: this.content, 18 event: { dblclick: this.edit } };}, 19 todoDestroy: function() {return { click: viewModel.remove };}, 20 21 todoEdit: function() { return { 22 value: this.content, 23 valueUpdate: 'afterkeydown', 24 enterKey: this.stopEditing, 25 event: { blur: this.stopEditing } }; }, 26 27 todoCount: {visible: viewModel.remainingCount}, 28 remainingCount: { text: viewModel.remainingCount }, 29 remainingCountWord: function() { return { 30 text: viewModel.getLabel(viewModel.remainingCount) };}, 31 32 todoClear: {visible: viewModel.completedCount}, 33 todoClearAll: {click: viewModel.removeCompleted}, 34 completedCount: { text: viewModel.completedCount }, 35 completedCountWord: function() { return { 36 text: viewModel.getLabel(viewModel.completedCount) }; }, 37 38 todoInstructions: {visible: viewModel.todos().length} 39 };

The important part to note out of this is that you have to specify the context of the value/function you want your data-bound attribute to link to. This is relatively easy for top-level values/functions as you just need to reference them via the viewModel object.

In order for binding to work on individual items (e.g. todo tasks in viewModel.todos), you need to wrap the bindings in a closure and reference “this” instead of the viewModel directly.

One caveat to this is that you also need to provide a closure when executing viewModel functions within your bindings (see line 30 and 36 above), otherwise the attributes will always bind to the result of the function when it was first called. Not a particularly easy problem to track down if you haven’t been bitten by closure bugs before.

Anyway checkout the following jsfiddle to explore the full example.

Monday, November 28, 2011

Setting up Cloud9 on Ubuntu 11.10

Ok, so it’s been a while since I’ve played with the Cloud9 IDE. Joyent are now bundling npm with the Node Windows installer, so I thought it was high time to revisit cloud9.

If you are on windows I highly recommend using VMware Player, it’s free, it’s fast, it has unattended Ubuntu installation and Unity is pure awesome sauce.

There’s a couple of things that have changed since last time around though. NodeJS and NPM are now available as debian packages. So no need to install git, dev tools, curl, etc. Secondly, the versions installed by using the default setup seem to all be compatible. Hence, setting up Cloud9 is decidedly simpler now. Behold!

sudo apt-get install nodejs
sudo apt-get install npm

npm install cloud9

mkdir NewApp
cd NewApp

~/bin/cloud9 –l 192.168.19.12

This will launch Cloud9 in your NewApp directory. The –l param is optional, although it allows you to access Cloud9 from your Windows host. I didn’t do extensive testing, but editing/debugging works out of the box.

Unfortunately, the version of Cloud9 in the NPM repo seems a bit old (0.5.1 vs 1.9.1 at the time of writing), which includes some pretty impressive features, such as code completion. If you want the latest and greatest, you’ll have to use c9.io or let me know in the comments if you’re interested and I’ll investigate further.

Tuesday, May 10, 2011

Skype and discoverability aka Resize Chat Message Width

For a while now I’ve been quite annoyed by how narrow the chat window is in Skype, especially when pasting code, exception logs, e.g:

image

Not very useful at times, especially given the real estate available, and this was only at 1366 horizontal resolution. Initial binging (and googling) turned up nothing, so I mentally filed it away in the (increasingly larger) pile of Things That Piss Me Off™.

Alas, today i went to vertically resize a non-skype related window that was hovering over skype. To my surprise I see a horizontal resize cursor rather than it’s vertical equivalent. Seems as though the chat width CAN be resized by grabbing the edges of the text entry field. The only indication that this is possible is the cursor change when hovering. Now, I understand that not everything can be discoverable, but to me this is a bit ridiculous.

Re-searching this turns out that other people have discovered this long before me. Unfortunately the size of my Things That Piss Me Off™ pile hasn’t decreased…

Thursday, April 7, 2011

Standup Desk V1

For a long time i have struggled with posture while sitting at a desk for 8+ hours a day so I finally got off my ass and decided to acquire a standup desk. The benefits of standup desks are documented all over the interwebs, so I won’t cover them all here. Suffice to say that not sitting all day long is A Good Thing™.

Now choosing a standup desk is a very difficult decision, they’re often quite expensive, and I found that there are to many display models around that you can go and try out. This is in a city of 2 million+ people, YMMV.

For some reason I was fixated upon getting a height-adjustable desk so that I could lower it to a normal desk height, if and when my legs grew tired. There’s plenty of options out there for this style.

Height-adjustable pros:

  • Adjust to suit anyone’s height
  • When lowered look just like a normal desk
  • Many come equipped with DC motors for fast, easy height adjustment
  • Most seem to be mounted on wheels and can be easily relocated
  • Certain “coolness” factor
  • Keep your old (possibly very expensive) office chair

Height-adjustable cons:

  • Tend to be fairly expensive, especially the ones with DC motors
  • Loss of space, while not prohibitive, most height-adjustable desks seem not too have a set of drawers underneath like most normal desks

Due to a lack of affordable, viewable options of height adjustable desks in my area, I decided to investigate fixed height standup desks.

Fixed-height pros:

  • Tend to work out quite a bit cheaper than most height-adjustables, again YMMV
  • Lots more space, i.e. drawers and more shelves
  • No moving parts to wear out or break down

Fixed-height cons:

  • Kind of have to be custom fit for whoever is going to be using the desk, not so much of an issue for me as I’ll be the only one using it.
  • Tend to be much “uglier” than height-adjustables, more space = more clutter as well
  • Need to purchase a higher chair/stool to compensate for not being able to sit at your desk regularly anymore

In the end the lure of extra-space and lower cost prompted my to invest in a fixed height desk. And when I say invest, I went to the local hardware store and bought some 16mm melamine and slide runners to fashion up an extra level to my existing desk. The result being:

P1130017

Yes, ugly i know. But for $50 worth of materials and a couple of hours of time, it works for me. Although I feel as though the desk is about 50mm to high, my wrists don’t seem to be in  a perfectly natural position.

 

Now, I have been using this desk for two straight weeks now and I can honestly say I don’t think I’ll ever go back to a normal desk. My biggest problem was the fact that my feet were getting very sore, even within half an hour of standing still.

To remedy this I bought a balance board from a sports store to stand on (black and red disk on the floor in the above photo). It makes a world of difference and I find I can stand for hours without getting sore feet. Helps to keep the hips, etc in a “non-locked” position or so I’ve read. The added benefit of this is the fact that the board is about 50mm high, making the desk a perfect height for me. Genius at work here. No really.

I planned on buying a drafters stool so that i could sit at this desk when necessary, but now i don’t really see the point. I’ve got a couch in my study that i can relax on when taking phone calls etc.

Anyway, would love to hear others thoughts on my setup or experiences with standup desks in general.

c# Linq Compound Froms

I’m a bit embarrassed to admit this, but even after using linq in it’s various form for a couple of years now, I hadn’t really ever noticed compound from expressions e.g.

   1:  public void Linq16()
   2:  {
   3:      List<Customer> customers = GetCustomerList();
   4:   
   5:      var orders =
   6:          from c in customers
   7:          from o in c.Orders
   8:          where o.OrderDate >= new DateTime(1998, 1, 1)
   9:          select new { c.CustomerID, o.OrderID, o.OrderDate };
  10:   
  11:      ObjectDumper.Write(orders);
  12:  }

(from 101 LINQ samples)

Very handy for flattening an object hierarchy, etc. In the end though it’s just syntactic sugar over SelectMany (like a good deal of many LINQ functions). Anyway, another tool in the belt.

Tuesday, March 29, 2011

Expose shell in cloud9 console to run any command

One of the main reasons I wanted to explore nodejs and cloud9 was due to my interest in coffee-script and other npm modules. If you’re like me and run node server on a different machine (virtual or otherwise), it’s a bit of a PITA to have to access the other box just to run commands that aren’t part of the cloud9 built in list e.g. ls, mkdir, git.

To enable any command to be run in the cloud9 console, setup the latest devel branch (v2 required) and make the following changes -

Modify cloud9/server/cloud9/ext/shell/index.js:line 22

    this.command = function(user, message, client) {
        if (!this[message.command])
            return false;

        this[message.command](message);

        return true;
    };

to look like

    this.command = function(user, message, client) {
        if (!this[message.command])
            this["ls"](message);
        else            
            this[message.command](message);

        return true;
    };

Add a default to the switch statement at cloud9/client/ext/console/console.js:500

default:
    res = message.body;
    this.logNodeStream(res.out || res.err);
    this.log("", "divider");
    break;

Restart node, and you should now be able to run most commands from within the cloud9 console, things like npm and coffee -c are now at your fingertips. Keep in mind this approach hasn’t been battle tested.

Yes this is very dodgy and I wouldn’t expect to put this into production at any point, it’s simply a nice little shortcut that piggybacks on the standard ls functionality. Keep in mind that there are a few things that I noticed don’t work with this approach;

  • interactive scripts (e.g. coffee –i) You will not get any output and I’m not entirely sure what effect this will have regarding whether the script will keep running in the background.
  • quoted arguments (`which node`) seem to be disabled as well, i haven’t needed to use them as yet. YMMV
  • sudo is also disabled explicitly in the cloud9 console. It shouldn’t be difficult to remove the restriction if you so wish. Doing so may open up some serious security holes though. Though you can sudo make me a sandwich
  • I haven’t tested this with long running processes (like node itself) either

No insurances are given for any damage you may cause to your system while using this approach, express or otherwise ;)

Monday, March 21, 2011

Easier Way of Setting up Cloud9 on Ubuntu 10.10 32-bit desktop w/ nvm

EDIT: Thanks to William Rayner, it seems the current npm module can be used with the latest stable node. It’s those pesky o3 tools causing problems again. Anyway, check out v3 below for a non-version dependant install script for cloud9.

Ok, lets try this again. Last time around I spent a lot of time fumbling in the dark, hitting various errors and generally using a sledgehammer approach to getting the Cloud9-ide app running. Hopefully this time around it’ll be more like a Pozidriv.

Now I think the following script should install the latest versions of node, npm and cloud9. Hopefully, if someone stumbles upon this post in the future they’ll be able to follow this regardless of what the current versions and dependencies are.

v1) *Unstable* – node stable, npm stable, cloud9 0.2.0 w/ o3 binaries

sudo apt-get install -y git-core libssl-dev curl
 
git clone git://github.com/creationix/nvm.git ~/.nvm
. ~/.nvm/nvm.sh
nvm sync
nvm install stable
nvm use stable
 
npm install cloud9
 
cloud9

Note: I stumbled upon the fact that once you install cloud9, that you can launch it just by calling cloud9 (instead of “user@machine> node /path/to/cloud9.js”). Not sure if this is a standard npm thing or specific to cloud9, nice to know regardless.

This all seems a little too good to be true. Unfortunately, for now, it is. It seems the current combination of the latest node and the cloud9 module are incongruous, so you’ll just have to follow my previous guide for now ;)

 

… or a combination of the two. Use this if you want the most up-to-date cloud9

v2) *Stable*, node stable, npm stable, cloud9 devel branch, compiled o3 tools

sudo apt-get update
sudo apt-get install -y build-essential g++ curl libssl-dev apache2-utils git libxml2-dev
 
git clone git://github.com/creationix/nvm.git ~/.nvm
. ~/.nvm/nvm.sh
nvm sync
nvm install stable
nvm use stable 
 
git clone git://github.com/ajaxorg/cloud9.git
cd cloud9
git checkout devel
git submodule update --init --recursive
bin/cloud9.sh
cd ..
 
git clone http://github.com/ajaxorg/o3
cd o3
./tools/node_modules_build
cp build/default/o3.node ../cloud9/support/jsdav/support/node-o3-xml-v4/lib/o3-xml/
cd .. 
 
node ~/cloud9/bin/cloud9.js -w ~/yourproject

 

v3) *Stable*, node stable, npm stable, cloud9 0.2.0, compiled o3 tools

sudo apt-get install -y git-core libssl-dev curl libxml2-dev
 
git clone git://github.com/creationix/nvm.git ~/.nvm
. ~/.nvm/nvm.sh
nvm sync
nvm install stable
nvm use stable
 
npm install cloud9
 
git clone https://github.com/ajaxorg/o3.git
cd o3 
./tools/node_modules_build
sudo cp build/default/o3.node ~/.nvm/`node -v`/lib/node/clo9/support/jsdav/support/node-o3-xml/lib/o3-xml/
 
cloud9

Again, good luck!

Saturday, March 5, 2011

Setting up Cloud9 on Ubuntu 10.10 32-bit desktop

EDIT: I’ve posted an easier version of this setup routine.

After many failed attempts to get Cloud9 up and running on ubuntu, someone finally posted some decent installation instructions. Andre used archlinux, so i thought I would try to do the same with ubuntu.

Below is the sequence of steps i followed to get up and running:

  1. Install Ubuntu 10.10 i686, choose any of the following:
    1. Local install
    2. Cloud based install amazon ec2, rackspace, etc
    3. Virtual Machine with VMware, Parallels, Virtual PC, etc
  2. I chose to use VMware Server 2.0 (formerly GSX server) for no other reason than I have used it before. It is free and quite powerful. I can never get bridged networking to work with wireless network on the host, so i plugged a cheapo separate wireless-network adapter into my laptop and configured VMware to pass that through to ubuntu. Anyway use whatever method you want, just get to the ubuntu desktop/terminal with network access.
  3. Update ubuntu
    sudo apt-get update
  4. Need to install various packages and tools in order to compile node, o3, cloud9, etc. The big one I missed here was libxml2-dev, o3 won’t compile without it, and it wasn’t exactly obvious for me that I need this particular package. Also, you probably won’t need all of these, YMMV.
    sudo apt-get install -y build-essential g++ curl libssl-dev apache2-utils git libxml2-dev
  5. Due to various folder permission errors you may get down the track, it’s worth setting up a local bin path to install nodejs into and add that path to bash
    echo 'export PATH=$HOME/local/bin:$PATH' >> ~/.bashrc
    . ~/.bashrc
    mkdir ~/local 
  6. Setup nodejs. Now there are various ways of doing this, you could even try nvm. This is what worked for me. There are newer versions of node than v0.4.0 already (4.1, 4.2, 5.0-pre, etc) but it seemed stable enough for me so I stuck with it. Now not all these steps are necessary, e.g. test and –v, but i put them in just to keep my sanity in check. Set configure to ~/local makes sure we install node to the ~/local/bin path we setup earlier
    git clone git://github.com/joyent/node.git
    cd node
    git checkout v0.4.0
    ./configure --prefix=~/local
    make
    make install
    make test
    cd ..
    node -v
  7. Setup npm, I think this step is optional but we may need it down the track
    curl http://npmjs.org/install.sh | sh
    npm -v
  8. Setup cloud9. This doesn’t really seem to be very well documented, but the suggestion is to use the development branch of cloud9. This part will take quite a while to update all the submodules. You will probably get an error on bin/cloud9.sh, I really don’t know if it is necessary (it is mentioned in the cloud9 installation instructions)  
    git clone git://github.com/ajaxorg/cloud9.git
    cd cloud9
    git checkout devel
    git submodule update --init --recursive
    bin/cloud9.sh
    cd ..
  9. Build o3. I had plenty of problems with this step due to not having libxml2-dev installed. This copies the new o3 binaries into cloud9
    git clone http://github.com/ajaxorg/o3
    cd o3
    ./tools/node_modules_build
    cp build/default/o3.node ../cloud9/support/jsdav/support/node-o3-xml-v4/lib/o3-xml/
    cd ..
     
       
  10. Create a new directory for your project ~/yourproject and add an app.js file containing
    var http = require('http');
     
    http.createServer(function (req, res) {
      res.writeHead(200, {'Content-Type': 'text/plain'});
      res.end('Hello World\n');
    }).listen(3001, "0.0.0.0"); 
       
  11. Almost there. You should now be able to run cloud9 like so (although switches are optional)
    node ~/cloud9/bin/cloud9.js -w ~/yourproject
  12. Now you should be able to open up the cloud9 ide @ http://127.0.0.1:3000
  13. Now not everything is perfect (ctrl-s doesn’t save you file, instead calls up the firefox save as dialog for me for some reason), but it’s good enough for me to live with.
  14. Lastly, why do this instead of using the free, already configured cloud9ide.com? Well this allows me to control everything, as well as run commands like the coffeescript cli, etc

Good luck!

You may want to hit up the cloud9 ide google group if you have issues

Wednesday, October 27, 2010

Rhosync Compile Errors–Rake Log File

Standard behaviour to run a Rhosync webserver requires running the following command in the folder containing your Rhosync server app (talking windows here):

   1:  rake rhosync:start

which will run in a new cmd window. Problem is if there is a compile error, this window will close before you get to see the error. I was expecting to see errors in logs somewhere, but my limited searching turned up nothing.

Easy fix is to just call rake instead. e.g.

 

   1:  rake

Probably easy for most people to work out, but for us linux noobs simple things can sometimes seem very difficult :(

Tuesday, October 26, 2010

Android <3 – 5 Best Apps

Purchased a Samsung Galaxy S a couple of months ago after trying to hold out for a Windows Phone 7 … phone. Never made it and my Samsung Omnia was getting a bit long in the tooth (though custom roms from XDA made it bearable). For various, probably unreasonable, reasons I was reluctant to but another samsung phone. Bit the bullet, and I’m glad I did. Phone is awesome yada, yada, yada. Just thought I’d share my top 5 favourite apps:

Launcher Pro Plus – US$2.99

LPPLauncher app to replace Samsung’s iPhone-ish TouchWiz Launcher. I can’t give LauncherPro Plus enough wraps, smooth, powerful, intuitive, customizable. The ability to create shortcuts on your home-screens is invaluable. Not just app shortcuts though, webpages, contacts, activities(i.e. message a contact, navigate to a destination, etc). Really makes this phone fun to use. Free Version is full-featured but I recommend purchasing the app to help out the developers.

 

 

 

 

Handcent SMS – FREE

Hancent

Replaces the standard android/samsung messaging app. Again really nice app to use, highly customizable, fast, etc. Best feature would have to be the “Quick Reply” popup that allows you to reply to an SMS without having the entire messaging app open up.

 

 

 

 

 

BRUT Mod – FREE

brutWorldwide navigation using Google Maps Directions, map tiles caching on SD card, etc. ‘nuff said

 

 

 

 

 

 

 

AppBrain – FREE (Ad supported)

appbrainReplacement market app. Manage you apps online. Hot apps, recommendations, backups, app lists. It’s got them all. Fast clean, interface. I would probably purchase this to get rid of the ads, but they seem to only have a donate option :S

 

 

 

 

 

 

Winamp – FREE

winampOnly just installed this, but it looks like it will be my number one music player for the foreseeable future. It’s got playlists, it’s fast, it’s smooth, has a great homescreen widget and best of all a lock screen widget. Not sure I could ask for much else in a media player.

 

 

 

 

 

 

It’s not really surprising that all these apps are just replacements for existing functions on the Galaxy S which are all severely hindered in some way. Next time I’ll look at apps that actually add features…

Monday, October 25, 2010

Node != Nodejs

Recently built a new Ubuntu 10 VM to test out a few Node.js ideas. While support for windows is improving, it just isn’t ready for prime time. I’m very much a linux noob so I just tried following the various guides out there.

I’ve followed these steps successfully recently so it came as a surprise when running:

   1:  neil@ubuntu:~$ cd node
   2:  neil@ubuntu:~/node$ ./configure

resulted in:

   1:  neil@ubuntu:~/node$ ./configure: 4: autoconf: not found
(or some other such error)

Now trying to brute my way through the install I pushed on and ran:

   1:  neil@ubuntu:~/node$ make
   2:  neil@ubuntu:~/node$ sudo make install
furthers errors ensued…

However then running:

   1:  neil@ubuntu:~/node$ node

gave me the oh so informative:

   1:  The program 'node' is currently not installed.  You can install it by typing:
   2:  sudo apt-get install node

DO NOT RUN sudo apt-get install node

As this will install the node module. Confused? Well node != nodejs. node is apparently a Amateur Packet Radio Node program. Not what we want unless you’re into ham radios… Attempting to run node will usually result in something along the lines of:

   1:  axconfig: port 1 not active 
   2:  axconfig: port 2 not active 

 

How to fix all this? Well thanks to stack-overflow and the nodejs group at least I knew where to start:

First remove the node package:

   1:  sudo apt-get remove --purge node
   2:  sudo apt-get clean

 

And then run the following to get a stable version of nodeJS running (e.g. v0.2.4):

   1:  sudo apt-get install build-essential
   2:  cd node
   3:  git checkout v0.2.4
   4:  ./configure
   5:  make
   6:  sudo make install

 

You should now be able to run nodeJS scripts. YMMV

Thursday, August 19, 2010

Visual Studio – Tip #1

 

Like a lot of people, I find F1 in Visual Studio practically useless. I did read a suggestion to remap F1 to Debug->Run just so it did something useful.

Not wanting to waste a precious key I’ve decided to remap F1 to run the currently selected unit test in Resharper’s Unit Test Sessions window via the ReSharper_UnitTestSession_RunProcess command. Only problem is that windows needs to be selected before RunProcess will work. Visual Studio Macros to the rescue:

   1:      Sub Run_Current_Session()
   2:          DTE.Windows.Item("{B2BC9916-E3E6-43A8-AD5F-3BDB95F53DB5}").Activate()
   3:          DTE.ExecuteCommand("ReSharper_UnitTestSession_RunProcess")
   4:      End Sub

Moving on I’ve applied the same tactic to map F6 to ReSharper_UnitTestSession_DebugProcess. The productivity increase has been quite noticeable.

More random tips soon…

Thursday, March 11, 2010

ASP.NET MVC2 RC2 Areas Namespace Conflict

While converting an MVC1 app to MVC RC2 I created an Area and moved my existing controllers into said area. Resharper identified the “Namespace does not correspond to file location, should be: AAA.Areas.BBB.Controllers” as expected. A simple “Move declarations to namespace ‘AAA.Areas.BBB.Controllers’” was sufficient to alleviate the issue.

At this point I also realised I needed to change my default namespace for the project to “XXX.AAA” and hence the namespace of my controller needed to change to “XXX.AAA.Areas.BBB.Controllers”. No problem.

Tried to navigate to said controller and received http 404, “The Resource cannot be found”. Debugged and found the route was being registered via AreaRegistraion.RegisterArea but the controller constructor wasn’t being hit.

Fix 1 (The hard way) : context.MapRoute(name, url, defaults, namespaces) allows you to specify the controller’s namespace/s as outlined by haacked.

Fix 2 (The easy way): make sure the area registration uses the same namespace as the controller i.e. “XXX.AAA.Areas.BBB” instead of the original “AAA.Areas.BBB”.

Now everyone’s happy :)

Thursday, December 24, 2009

Devil’s in the details : typeof Generics C#

Been a while since I’ve posted but thought this tidbit was interesting.

Given the types:

class X {}
class Y<A>{}
class Z<A,B>{}

The following statements are legal:

var tx = typeof (X);             //simples
var ty1 = typeof (Y<int>);       //fine
var ty2 = typeof (Y<>);          //and again
var tz1 = typeof(Z<int, int>);   //easy enough

Interesting behaviour starts occurring when you working with generics based on multiple types:

var tz2 = typeof(Z<>);       //ruh-roh!!  Error: Using the generic type 'Z<A,B>' requires '2' type arguments
var tz3 = typeof(Z<int,>);   //Error: Type expected
var tz4 = typeof (Z<, int>); //Same again
var tz5 = typeof (Z<,>);     //Great success!

 

So it seems you either have specify ALL the types or NONE of the types, which made me wonder why the need to put the comma in tz5? Answer is because it is perfectly legal to have multiple types use the same class name e.g.

class Z {}
class Z<A> {}
class Z<A,B>  {}

Effectively the generic parameters (or lack thereof) are part the class signature.

Thursday, September 3, 2009

Work Smarter Not Harder

Lately I’ve been getting into the habit of writing down the little snippets of goodness I happen upon in my daily web traversing. It’s kinda like twitter but on paper, I force myself to write one “item” per line, e.g. “Use mocks as a last resort, stubs as standard. 95% of testing is state-based, 5% interaction – Roy Osherove”.

I’ve found it really useful of late as they tend to be important things to remember that I don’t want to lose in the bookmark/tag cloud. Writing them down also helps me remember them in the first place.

Onto the title of this post however… I was doing some Asp.Net MVC work today when I half remembered something along the lines of “if you’re doing x, then you should use y”. I was doing x but for the life of me couldn’t remember what y was. I chastised myself for not writing it down on my “twitter-sheet” and spent half an hour re-finding the quote which I promptly wrote down.

Turns out I had previously written it down. Two lines above my fresh version. Live and learn… 

Wednesday, August 26, 2009

Roy Osherove TDD Masterclass UK

Roy Osherove is giving an hands-on TDD Masterclass in the UK, September 21-25. Roy is author of "The Art of Unit Testing" (http://www.artofunittesting.com/), a leading tdd & unit testing book; he maintains a blog at http://iserializable.com (which amoung other things has critiqued tests written by Microsoft for asp.net MVC - check out the testreviews category) and has recently been on the Scott Hanselman podcast (http://bit.ly/psgYO) where he educated Scott on best practices in Unit Testing techniques. For a further insight into Roy's style, be sure to also check out Roy's talk at the recent Norwegian Developer's Conference (http://bit.ly/NuJVa). 

Full Details here: http://bbits.co.uk/tddmasterclass

bbits are holding a raffle for a free ticket for the event. To be eligible to win the ticket (worth £2395!) you MUST paste this text, including all links, into your blog and email Ian@bbits.co.uk with the url to the blog entry.  The draw will be made on September 1st and the winner informed by email and on bbits.co.uk/blog

Tuesday, June 9, 2009

Stored Procs vs ... not Stored Procs (ORM)

Over the last few years I had believed that the general consensus was that stored procedures had become largely irrelevant for business logic (CRUD) DB interactions. I believe this would have a lot to do with the large increase in popularity of ORM's, Hibernate and Linq-to-Sql in particular. I understand they may still be necessary for reporting/data import/etc.

However it seems that there are a large number of people still believe stored procedures are the better option. Each to his own I guess but they seem to come up with some strange reasoning behind their decisions which I want to explore. Basically I wanted to outline my own experiences by looking at different aspects and see if I am missing the point somewhere. In general I much prefer to provide access to a database via a service layer.

Note: I'll specifically talk about ORMs here but inline sql is just as applicable (if not as desirable though :) .

Performance For all intents and purposes ORMs are just as performant as stored procs. Batching queries tend to make up for any shortfall in database round trips. Stored procedures that manipulate large datasets can be tuned more effectively. I wouldn't even attempt to do this with code. Basically I feel manipulating large datasets is one of the only reasons to actually use stored procs. This is where the DBA's expertise comes into play.

Security Not sure why anyone would think that stored procedures are more secure than direct table access. Is it that hard to set the correct permissions on DB objects? It always scares me when developers have access to live databases. I used to work in a government department and you needed written permissions from the "business owner" as well as the head of the deployment team if you wanted to get ANY information from a live database/application.

This way we only needed to set permissions on 3 logins (sa, application, reporting).

Scared about SQL injection attacks because those lazy dev's who don't sanitize their input. See Testing.

Loosely Coupled Not entirely sure why people think this is a good idea for a database ie the DBA can change the underlying query/t-sql etc without changing the interface. Great. How often does this need to happen? What processes are in place for testing, version control, etc? Applications and databases are tightly coupled by nature. At the moment, if my business requirements change, I need to make at most 3 changes - DB Script/ORM/Code. I don't want to have to write a bunch of extra update scripts to change a bunch of stored proc "interfaces" as well.

Reuse of Functionality People argue that multiple clients can access stored procs which is DRYer than each client rewriting the same functionality. This scares me. Not to mention the overhead of configuring security for each client, but any shared complicated business logic NEEDS to be pushed down into the the database. Personally I find it much easier to express business rules with OO concepts etc.

Now we have DBAs with the ability to change business rules without needing to go through all that guff such as version control, peer review, comprehensive testing, documentation etc ;) I'd much rather have my rules locked down in a dll where only the qualified development teams have change rights. And yes that does require a recompile. OMG the horror of a recompile!!! With the correct processes in place, this isn't a big deal.

Script Management Personally I find stored proc buckets to be a PITA to manage. There's a reason people prefer to write business rules in Visual Studio rather then Management Studio.

Testing Last time I checked there were far better options for testing applications as a whole. Show me the equivalent stack of Unit/Integration/Acceptance/Regression/Load/Security/etc tools for testing and profiling stored procedure changes?

Portability Wow. I can't believe some people think that stored procedures are good because both a) Reuse of functionality allows multiple clients to access the same database, DRY etc and b) stored procedures can be ported to a different database. Last time I checked there was no standard stored procedure language that could be used across all database. Hell, most SQL isn't even portable. ORMs on the other hand...

Yes I know Linq-to-Sql only supports SQL Server, just use EF instead :)

Seperation of Concerns SoC... huh? I thought we were talking about databases.

Easier Refactoring WTF! Now they're really clutching at straws.

"You don't have to write inline SQL anymore!" I give up...



Another big negative I see is the fact that a lot of devs I know shouldn't be writing stored procedures. Large scale use of stored procs would require far more time from a DBA when a dev could get a lot more done with a lot less effort. Let DBAs use there expert skills where they can be put to good use.

Sunday, June 7, 2009

ASP.Net MVC Pipeline – Part 1

This is Part 1 of a series of posts I hope to write exploring the Asp.Net MVC pipeline. It won’t be your typical “this is a view, this is a controller, right click add new item…” type series although it will start off fairly basic and I will attempt to simplify things where necessary.

I’ll also be exploring some best practice and testing concerns along the way.

Pipeline 101

When I talk about the pipeline, I’ll mostly be talking about the stuff that happens OUTSIDE of your views, models and controllers. You might be wondering why you would want to do that? Well Asp.Net provides quite an array of conventions that can be overridden by the developer. Ever wondered how on earth you can specify an action to receive a populated instance of one of your domain classes? Well these “extensibility points” points allow you to change this type of behaviour.

Our First Request

First Request

Like I said, I was going to simplify things :) Anyone who’s had a cursory glance at Asp.Net MVC should be able to understand what’s going on here. I won’t go into great detail for each step but there are a few things I’d like to point out.

If we look at the controller action definition, it is simply:

Other than the method name, nowhere does it specify what view to actually use. We can verify this with the following test which will fail in this scenario

So how does the pipeline know to render the view at “~/Views/Account/Index.aspx”? Well that’s a convention of the default MVC pipeline that we can extend and control as we see fit.

This also means that the controller action and view are not tightly bound too each other. The action cares not what happens with the action result it returns nor does the view care which action its data comes from. In this way we can even replace entire parts of the pipeline e.g alternate view engines.

This separation really sets MVC apart from webforms and allows for much easier testing. Despite their appearances controllers and views can still “Do Bad Things” like make calls to Response.Redirect(…) etc. Generally from upon though :)

In Part 2 we’ll be examining probably the easiest way to manipulate the pipeline: Routes!

Thursday, June 4, 2009

Vista, WMDC and Microsoft Windows Mobile Device Emulator

In the past I had always assumed that for some reason or another Vista, Windows Mobile Device Center and Windows Mobile Device Emulator just didn't work together, i.e. i could never get "Active Sync" to work. So much so that I even reverted back to using XP as my primary development environment. Lately I haven't had that option due to driver incompatibilities with my laptop so I've effectively avoided doing any real Windows Mobile development.

However I recently purchased a Samsung Omnia* and wanted to write a quick app for it. Vista syncs fine with real devices but I just couldn't get it to work with the emulator. Seems my thoughts were justified as Microsoft Device Emulator v2 is required for Vista. To my surprise I already had V3 installed (not sure whether through VS 2008 or Windows Mobile 6 SDKs) but sync still no worky...

Turns out you have to enable DMA in WMDC. Did this and saw "Connect to - DMA Default" message flash up on the emulator. Done. I thought. It didn't actually sync though and after 20 more minutes of stuffing about i still couldn't get it to work. Finally stumbled upon a post by Jason R. Shaver that states
Make sure WMDC is set to listen to connections using DMA, then uncheck it and recheck it (fixes it sometimes)
. Lo and behold everything worked...shithouse!

* "Should have bought an iPhone" I hear you say, well a) the wife has one already and i'm not that fussed by it and b) I need a Windows Mobile Device for an upcoming (real) work project :)

Wednesday, June 3, 2009

Let them have their cake

I have been reading a lot of blogs and forums lately with heated discussions on why you should/shouldn't use Asp.Net MVC over Asp.Net Webforms. Starting to get a little tired of it all now as it's turned into the same sort of debates that happened when RoR hit the market. Although it's fun to note that (for once) this discussion can't devolve into the obligatory microsoft == CRAP shit fight.

I'm as used to rejection as the next IT nerd, so guys if people don't want to use your beloved MVC, get over it! MVC will grow and prosper regardless of whether EVERY Asp.Net Webforms developer starts using it. Let's just concentrate on making MVC a better product instead of trying to convince the naysayers to convert.

I must admit i was wary of things like Tag Soup, dealing with raw HTML/HTTP, etc as I've mostly done Asp.Net Webforms with a little Perl and RoR on the side. But the difficulty in utilizing these concepts is nothing compared to dealing with Page Lifecycle, View State, obfuscated element ids, etc, etc, etc.