Hackery: Line following bots at CodeMash

NodeBots @ CodeMash

CodeMash 2.0.1.5, the latest installment of the popular community-organised conference is fast approaching. This time, I will be attending with several of my colleagues from CareEvolution, which is sponsoring the NodeBot precompiler sessions. One such colleague and good friend, Brian Genisio (also a co-organiser of the Southeast Michigan JavaScript group more commonly known as SEMjs) has been working night and day for months to prepare for each of the two epic software and hardware hacking events that will be the NodeBot precompilers. Though myself and a few other friends (many of which you can meet in person at CodeMash) have assisted Brian over the last few weeks, the success of this event really is down to his vision and commitment. From creating documentation to submitting Johnny Five pull requests1, ordering components to building kits, Brian's efforts have been considerable; if you join us to hack NodeBots (and you really should), be sure to take a moment and show him your gratitude.

My biggest contribution to the NodeBots preparation was to organize and take part in a hack day at work where Brian, a few colleagues (Brandon Charnesky, Greg Weaver, and Kyle Neumeier), John Chapman (another co-organizer of SEMjs and the NodeBots precompilers), and I could test and finalize kits and components, review and update documentation, and give some of the challenges and components a dry run in the process. Participants at CodeMash will be able to take part in one of two competitions with their NodeBots; a sumo-inspired Battle Bots competition where bots can compete for supremacy in the ring, or a line racing time trial where bots must follow a track in the fastest time2. My main efforts during the hack day were to create a sample line-following bot and provide some example code as a starting point for our precompiler hackers. The examples for both the basic line follower and basic sumo bot, as well as some other examples for specific components, can be found on GitHub in the CodeMash NodeBots Docs repository. Instructions on getting started are available on the official CodeMash NodeBots website.

Healthcare and NodeBots?

CareEvolution logo

Some of you may have been wondering: "why would a healthcare IT company like CareEvolution chose to sponsor an event hacking robots?" If you would like to know more, please come to our vendor session at CodeMash (2 p.m. on Thursday, January 8) where I will be presenting "We're Not All Robots: Hacking NodeBots, Healthcare, and the Workplace".

The Line-Following Hardware

Before hacking the code, I needed to work out how the hardware worked and build my bot. I started out with the IR (infrared) reflectance array component; an array of six IR emitters and corresponding receivers that will be the eye to see the line.

IR array and cable
IR array and cable

In the image above, you can see the front of the array as well as the cable to attach the array to the controller (we are using Arduino Uno clones for the precompilers). Using the pins already attached3, I connected the array to the board.

Rear of array showing attached pins
Rear of array showing attached pins
Wiring diagram of reflectance array connected to the controller
Wiring diagram of reflectance array connected to the controller

In the wiring diagram above, you can see each of the six analog pins on the Arduino going to one of the output pins (labelled 1-6) on the reflectance array4. Pin 13 of the Arduino has been connected to the LED ON pin of the reflectance array, which is used to activate the infrared LED's.

With everything connected, I used the usage code from the Johnny Five documentation to create a quick tester and verify that I was able to receive output from my reflectance array.

var five = require("johnny-five"),
    board = new five.Board();
 
board.on("ready", function() {
  
  var eyes = new five.IR.Reflect.Array({
    emitter: 13,
    pins: ["A0", "A1", "A2", "A3", "A4", "A5"]
  });
 
  eyes.on('line', function(err, lineValue) {
    console.log( "Line Position: ", lineValue);
  });
 
  eyes.enable();
});

After verifying the reflectance array was wired and working, I followed the reference kit build instructions to create a robot chassis on which I could mount the reflectance array.

Reference bot
Reference bot

I then mounted the array at the front, near the wheels, using some padded double-sided tape (the array must be within a quarter of an inch of the line, so a little padding was required). To avoid confusion, the array was oriented so that its left (pin 1, according to the documentation) was also the bot's left (assuming the wheels are the front of the bot).

Reflectance array mounted at the front of the bot. Pin 1 is on the right in this picture (the bot's left).
Reflectance array mounted at the front of the bot. Pin 1 is on the right in this picture (the bot's left).

The Line-Following Software

With the bot constructed, I needed to tell it what to do. My aim was not to create the best line-following bot ever (that is a task that possibly awaits you at CodeMash), I merely wanted to make something that demonstrates the basic concepts.

The first thing that the bot needs to do is to "see". Although we had a little code to check the array worked, we had not actually calibrated the array. Calibration allows us to show the array the extremes that it is to understand, i.e. the materials that represent the existence and non-existence of a line. Thankfully, the Johnny Five driver for the reflectance array makes calibration easy with the calibrateUntil function.

var five = require("johnny-five");
var board = new five.Board();

var stdin = process.stdin;
stdin.setRawMode(true);
stdin.resume();

board.on("ready", function () {
    var eyes = new five.IR.Reflect.Array({
        emitter: 13,
        pins: ["A0", "A1", "A2", "A3", "A4", "A5"]
    });
    
    var calibrating = true;
    
    // Start calibration
    // All sensors need to see the extremes so they can understand what a line is,
    // so move the eyes over the materials that represent lines and not lines during calibration.
    eyes.calibrateUntil(function () { return !calibrating; });
    console.log("Press the spacebar to end calibration...");
    
    stdin.on("keypress", function(chunk, key) {
        if (!key || key.name !== 'space') return;
        
        calibrating = false;
    });

    eyes.on("line", function(err, line) {
        console.log(line);
    });
    
    eyes.enable();
});

In my updated code, I also added keyboard input capture so that the calibration mode could be exited via the space bar. Running this with my bot, I was able to drag a piece of paper with a thick black electrical tape line under the array and calibrate it. After calibration, I could see from the console output that my bot recognised the line and in which direction it had last seen it5.

Next, I needed to be able to move the bot based on the line position. For this, I added some simple wheel commands and thresholds. The code is shown below.

var five = require("johnny-five");
var board = new five.Board();

var stdin = process.stdin;
stdin.setRawMode(true);
stdin.resume();

board.on("ready", function () {
    var wheels = {
        left: new five.Servo({ pin: 9, type: 'continuous' }),
        right: new five.Servo({ pin: 10, type: 'continuous' }),
        stop: function () {
            wheels.left.center();
            wheels.right.center();
        },
        forward: function () {
            wheels.left.ccw();
            wheels.right.cw();
            console.log("goForward");
        },
        pivotLeft: function () {
            wheels.left.center();
            wheels.right.cw();
            console.log("turnLeft");
        },
        pivotRight: function () {
            wheels.left.ccw();
            wheels.right.center();
            console.log("turnRight");
        }
    };
    
    var eyes = new five.IR.Reflect.Array({
        emitter: 13,
        pins: ["A0", "A1", "A2", "A3", "A4", "A5"]
    });
    
    var calibrating = true;
    var running = false;

    wheels.stop();
    
    // Start calibration
    // All sensors need to see the extremes so they can understand what a line is,
    // so move the eyes over the materials that represent lines and not lines during calibration.
    eyes.calibrateUntil(function () { return !calibrating; });
    console.log("Press the spacebar to end calibration and start running...");
    
    stdin.on("keypress", function(chunk, key) {
        if (!key || key.name !== 'space') return;
        
        calibrating = false;
        running = !running;
        
        if (!running) {
            wheels.stop();
            console.log("Stopped running. Press the spacebar to start again...")
        }
    });

    eyes.on("line", function(err, line) {
        if(!running) return;
    
        if (line < 1000) {
            wheels.pivotLeft();
        } else if (line > 4000) {
            wheels.pivotRight();
        } else {
            wheels.forward();
        }
        console.log(line);
    });
    
    eyes.enable();
});

The first thing I added was a wheels object to encapsulate the motor controls. Movement is provided by two continuous servos attached to pins 9 and 10. After defining left and right servos, I created the following methods:

  • forward
    Both servos turning such that they rotate toward the front of the bot
  • pivotLeft
    The left servo rotates in reverse while the right servo rotates forward
  • pivotRight
    The right servo rotates in reverse while the left servo rotates forward
  • stop
    Both servos stop moving

Next, I made sure that stop()  was called on startup to ensure the bot was not wandering around aimlessly. I then updated the space bar handling to act as a toggle that on first use stopped calibration and started the bot on its line following quest, but on subsequent uses merely stopped or started the line following. Finally, I added some thresholds to the line  event handler to determine when the bot should drive forward and when it should pivot in either direction based on the value sent from the array.

And with that, my simple line-following robot was complete. It does a fair job at following a course, but it is in need of fine tuning if it is to win any races. Perhaps you will be up to the task when you take part in the CareEvolution-sponsored NodeBots precompilers at CodeMash 2.0.1.5. If you wish to take part in our hacking extravaganza, you will need to register, so be sure to reserve your spot.

  1. which earned Brian the privilege of becoming a core committer []
  2. of course, you don't have to compete in either; you can just hack []
  3. thanks to the efforts of John Chapman, no one will need to solder pins to the reflectance arrays []
  4. pins 7 and 8 are unused as the reflectance sensors for those pins have been separated from the component []
  5. the `line` event from the array uses 0 to mean the line was last seen to the left and 5001 to mean it was last seen to the right; any value between 1 and 5000 means the line is under the array with the value indicating its position []

Kicking the Habit

This is a long story. I have never written it down before or told it in its entirety because I never really saw it as worthwhile to do so. However, recently I have learned some new lessons and have come to realise that sharing this might be useful to me and perhaps others. So, take a comfortable seat and I shall begin.

In the beginning…

When I was very young, I remember taking a puff on my Uncle Jeff's pipe. The sweet smell of pipe tobacco, both before and after it was alight, and the mischievous nature of my uncle were enough to lure me in. One attempt at smoking it was enough to put a stop to that nonsense and I vowed I would never smoke again.

What the hell did I know? I was just a kid.

When I was around nine or ten and with my memories of early pipe experimentation faded, a friend and I discovered a pack of cigarettes on the stairs of my house. It had been left there by a contractor who was doing some building work for my parents. My friend and I had often pretended to smoke by lighting dried bracken stalks (we never inhaled – goodness knows what carcinogens are in that smoke), but now we had the opportunity to try the real thing. It only took a brief tête-à-tête to convince each other we should take one.

Later that afternoon and with a pack of matches from by the fireplace, we went for a walk down the fields. Once we felt we were secluded from prying eyes, we lit the cigarette. I do not recall who went first, but I do recall that whomever it was, their coughing and watering eyes did not deter the other. As we played it cool, denouncing tobacco as "no big deal", the cigarette was stomped out and we walked home again.

And that was that. For years, that was that. Even though my grandmother and her cousin had smoked around me for many years. Even though my uncle smoked his pipe. Even though a number of my cousins smoked, and people my parents knew smoked, and I often encountered smokers when out and about, that was that. Smoking was not for me.

Social Smoker

And then I started working at my local pub. Some of the friends I had smoked and so, when we were out drinking, I would occasionally have one. I was a social smoker. No big deal. I just had one every now and then. I was not addicted, it was just fun. One, maybe two cigarettes a month. No big deal.

That continued through my early years at university until 2000, my graduation year. In 1999, I had moved in with a drug dealer. This was not my plan, I should note, it just was. My landlord from the previous year had offered me a spare room in this house and it was already occupied by two friendly girls and a drug dealer. The girls moved out within two days of my moving in. They knocked on my door the day before they left to let me know that it was not my fault and that they really liked me, but that drug dealer guy, yeah, he was something else. They had to leave. And so they did. Shortly thereafter, one of the drug dealer's friends moved in. A few months later, everyone but me moved out.

There are many stories from that final year, including some that I am unlikely to share. As I think back, 2000 turned out to be quite eventful for me. I graduated university, got my first mobile phone, lost my virginity (I was always a "late bloomer", as some say)1, lived with a drug dealer, and started smoking.

Before the drug dealer and his friend moved out, there were many nights of watching movies and smoking in the lounge of our house. When you live with someone, you overlook some things in order to have a peaceful existence, and so I overlooked some things. At some point, during this, I started smoking. I guess I felt it was better to actively smoke my own rather than passively smoke theirs. Whatever it was, by the time May rolled around, I was alone in the lounge, in the whole house, smoking.

I tried to quit. I figured I had only started in February so surely I can just quit. I was only smoking five or ten cigarettes a day. Quitting would be easy. Little did I know that after four months of smoking, it would take me years to quit. I was an addict, regardless of whether I acknowledged that or not.

Addicted

Many times I tried to quit. Before I started my first job out of university, I quit. I even advertised "non-smoker" on my CV as if that would somehow make me stand out. Only a week or two into the job, I was smoking again.

I quit using nicotine patches, then started smoking while wearing the patches.

I quit cold turkey, then slipped up having a beer one night and let guilt side with my addiction in the morning.

I quit and quit and quit. Each time, the addiction seemed to come back stronger than before. Like a friend, it was always there when things were difficult, stressful, or uncomfortable.  It could be relied upon. Each time I fell back into its embrace I would be disgusted with myself to the point that I would squeeze harder, searching for some comfort. What a terrible thing, addiction.

In early 2005, an opportunity arose to try a job in the US and so I did. Eighteen months later, after talking about it with some good friends, reading the autobiography of a quadriplegic alcoholic, and reviewing all the ways I had failed to quit before, I decided to quit again. This time I signed up to a smoking cessation website, listened to a self-hypnosis MP3, and started using nicotine gum.

I had my last cigarette on August 31st, 2006. I know because, after finishing the autobiography, reciting the serenity prayer to myself, and having one last cigarette on the balcony of my apartment, I wrote the date down. This was a lesson I had learned from trying to quit before.

1. Remember when you stopped smoking and why

Before, after about three months, complacency had set in. I had beaten this addiction. I could control it. So, one cigarette won't hurt. But it will, every time. By writing down the date, committing it to memory, I was always able to remember when it was and recall all the effort, as well as calculate how much money I had saved. By writing down why I quit, I could remind myself of what the effort was for and why it mattered.

For those first few weeks I was a grumpy, short tempered arse. I could not help it. I warned friends and coworkers what to expect. They were incredibly supportive. This was another lesson.

2. Tell people you stopped smoking

It was important that people knew so that they could be supportive. They could give me some slack when I got a bit ratty and they could keep me honest when I came close to having a smoke.

The nicotine gum really helped with this too. By using gum, I was able to keep my smoke break routine, get a hit of nicotine, and avoid smoking. Another rule.

3. Keep the challenge small

In the past, I had tried to change too much. For example, to avoid gaining weight (a common occurrence when giving up smoking), I would commit to working out more and dieting while trying to quit. However, bundling things like this is a terrible strategy because failure of one tends to cause failure of the others. All paths would lead back to smoking.

Of course, that didn't mean I had to do everything else the same. There were triggers to smoking. Times when smoking would come to mind more strongly than others. All my failed attempts at quitting had highlighted some of my triggers. It turned out that all those failed attempts were actual lessons on how to quit.

4. Learn your triggers

By analysing my previous attempts to tackle my addiction, I was able to identify my triggers, such as,

  • Going out drinking
  • Coffee breaks
  • Leaving the gym
  • Driving
  • Boredom

And so, with nicotine gum, supportive friends, and effort, I stopped smoking. Until I had another cigarette while visiting the UK. I was drinking at my local pub (a trigger) and a neighbour had a smoke. I asked him for one. He refused, saying I had quit. I pressed him and he gave in. It was not his responsibility to stop me smoking, it was mine and I failed. I enjoyed that cigarette as I walked home. However, unlike other times, when I awoke in the morning I remained smoke free.

5. Accept that mistakes do not mean failure

A terrible aspect of nicotine addiction (and I suspect addictions in general) is that addicts punish themselves over any slip or fall, which causes them to run into the arms of the only friend they can rely on, their addiction. It's vicious and if you are not looking out for it, inevitable.

You have to allow yourself to be fallible and accept that you will screw up. Whether it is relationships, your addiction, or some other aspect of life, you will screw up. Changing my mindset to accept that I might slip up but not allowing it to derail my effort was one of the most difficult things to do, but ultimately, it is possibly the biggest aspect of coping with addiction.

By the end of August 2013, I had been almost entirely smoke free for six years. It was great.

An old familiar friend

By now, you might think you know where this is headed and in part, you could be right. The end of 2013 was pretty rough. We had a terrible winter and I was suffering from depression. This ultimately led to me doing something I should have done years before. I sought help and entered therapy. As 2014 drew on, I delved deeper into what made me tick, why I did the things I did and felt the way I felt. It was liberating and emotional and terrifying.

Without really noticing, I turned to an old familiar friend. It started much the same way as before. I tried a cigarette while out with friends (a trigger) and hated it, but I knew I used to like it, so I did it anyway. Then it was just a social thing. Just one every now and then. Suddenly, a month or two ago, I was buying a pack and sneaking around to have a smoke. I convinced myself I was in control. I could stop any time. I could quit. After all, I'd done it before, hadn't I?

No. Clearly, not.

I knew it had to stop and told myself, "Today is the day I stop."

The next day, with five cigarettes left in the pack, I had one more. One wouldn't hurt right? Then I would stop.

I finished the pack and then, I stopped. My wife spoke to me about it soon after my last cigarette (you can't hide that smell, no matter how hard you try) and also, quite rightly, demanded I stop. I even spoke to my therapist about it to see if I could work out why it happened and what I needed to learn to get my addiction under control again.

So, here I am, one week in, with nicotine gum in my cheek, learning how to control my addiction. Because that is all I can hope to do, control. I will always be a nicotine addict, I just hope that I can retain control such that I can live without nicotine. Armed with all the lessons from my missteps along the way, I just might.

I hope that by sharing some of the details from my struggle with addiction in general and nicotine addiction in specific, it will be helpful to others. Perhaps some of you might like to share your own experiences with addiction in the comments. For now, this will serve as a reminder to my future self when that old familiar friend comes calling. I am Jeff, I am an addict, and I have been smoke free since December 10th, 2014.

  1. though I have always felt uncomfortable with the flower analogy []

Five things to love about modern.IE

You might be surprised to learn that the browser testing resources website, modern.IE (provided by Microsoft) is not just about Internet Explorer. Although some of the features are geared solely toward IE testing, some are browser-agnostic and can be very useful when developing websites. Here are a few of the things modern.IE can do for you.

Virtual Machines

Download virtual machines

Working on websites often means debugging using different browser variants. Unless you are exceedingly lucky, that will include older versions of Internet Explorer. While services like BrowserStack are invaluable for testing, they cost money and are not always responsive enough for productive debugging. Instead, I have found virtual machines (VM) to be much more useful.

Microsoft has been making VM's available for Internet Explorer testing via the website modern.IE for quite some time now. You can download VM's for whatever development platform you have, whether it is OS/X, Windows, or Linux.

Available versions of Internet Explorer
Available versions of Internet Explorer
Select virtual machine platform
Select virtual machine platform

Azure RemoteApp

If you want to test your work against the latest Internet Explorer in Windows 10 and you do not want to download a virtual machine, or are working from an unsupported device, Azure RemoteApp is for you.

Azure RemoteApp

All you need is a Microsoft Live ID and you can login and test with the latest IE for free.

Browser Screenshots

Browser Screenshots

Just want to check what your site looks like across various browsers and devices? The Browser Screenshots feature of modern.IE will give you screenshots across nine common browsers and devices. Somewhat surprisingly (at least to me), this includes more than just Internet Explorer; at the time of writing, you get:

  • Internet Explorer 11.0 Desktop on Windows 8.1
  • Opera 12.16 on Windows 8.1
  • Android Browser on Samsung Galaxy S3
  • Android Browser on Nexus 7
  • Mobile Safari on iPhone 6
  • Safari 7.0 on OS X Mavericks
  • Chrome 36.0 on Windows 8.1
  • Firefox 30.0 on Windows 8.1
  • Mobile Safari on iPad Air

Not only will it give you the screenshots, but you can share them with others, generate a PDF, and more.

Site Scan

This scan checks for common coding practices that may cause user experience problems. It will also suggest fixes when it can. Not only that, but the source is available on GitHub so that you can run scans independently of modern.IE and the Cloud.

Site Scan

I ran this against my blog and it took just over seven seconds to return the results.

Compatibility Report

Compatibility Scan

This feature will scan a given site for patterns of interactions that are known to cause issues in web browsers.  The first time I tried to run this, it did not work. However, a second attempt gave me results.

Why software bugs exist and how you can help

Numbers in software development are represented by fixed size variables represented in binary. These are usually 8, 16, 32 or 64 bits (each bit represents a 1 or a 0). When we develop software, we choose which of these will provide enough space for the thing we are representing.

Recently, the Gangnam Style video on YouTube surpassed 2,147,483,647 views and it appeared as though the view counter broke. That number is significant because it is the upper limit of a 32-bit signed integer. It turns out that the video view count was being represented using a 32-bit signed integer — a signed value1 can represent whole numbers in the range -2,147,483,648 through 2,147,483,647; it cannot represent any number outside that range.

Though, according to YouTube, this turned out to be an Easter egg2, the bug was there before they updated the counter to 64-bit and it certainly is not the first time a number has pushed the limits. For example, the use of two digits to represent a year that contributed to the infamous fizzle that was Y2K.

But why? Why are there bugs at all?

Although it may seem like software bugs are there just to ruin your day, they were not intentionally put there or maliciously inserted to give you a reason to "Office Space" your device. As software engineers we have to consider a variety of constraints on the software we are developing. How much space does it need to run? How much space will there be on the device on which it is to run? How fast does it have to be?  How many years will the software be in use3? What other software will be running? And we have deadlines by which our work has to be completed. In fact, software engineers tend to consider a whole host of things such as the requirements of the software (functional, spatial, and temporal4), the specification of the system on which it is to execute, project deadlines and budgets, and the expectations of the end user.

Almost always, there has to be compromise. Even though a solution might be possible that accommodates all considerations, we have to deliver software in a time frame that people will pay for and some things just take too long or cost too much. That is not to say that all software bugs are because of time and money, some exist because of mistakes and as a consequence of poor design.

What does it all mean?

Software engineers like myself do not want you to encounter bugs. We work very hard and the QA teams work very hard to ensure that you do not get buggy software; if we see a problem, we do what we can to address it. To find these bugs, we try to consider all the ways our software might be used and test them. Unfortunately, most bugs do not advertise their existence quite so obviously or politely as YouTube's view counter bug. For example, when in comes to the infinite ways any one device might be configured with different peripherals and apps installed, we just cannot test them all; the system is too complex5.

 Good developers welcome user feedback. We need your help.

Next time you encounter a bug in the software you use, whether it is a mobile app, a website, an ATM, a desktop application, or some other device, spare a thought for the software engineers. Remember, good developers welcome user feedback. Take a moment to tell them or the publishers of the software about the problem.

  • What did you type, touch, or click?
  • What else was running on your device?
  • What part of the software were you in?
  • What Internet browser or operating system were you running?
  • What versions?

Be as detailed as you can. All these details and more can help a software engineer track down, reproduce and ultimately fix that bug.

There is no malice in a software bug. It was not put there specifically to ruin your day. However, without your help, it will not go away. So, reach out to the developers and tell them, they will thank you for it.

Today's featured image is based on Software Bugs by Martin Maciaszek.

  1. signed means it can be positive or negative []
  2. An Easter Egg is a hidden feature often added to software as an amusement for users who find it. Examples include the "barrel roll" in Google or the flight simulator in Excel []
  3. Underestimation of this was a big contributor to Y2K []
  4. i.e. how it works, what space it needs, and how long it takes to run and for how long it has to run []
  5. That's a discussion for another time []

Some of my favourite tools

Update: This post has been updated to recognise that CodeLineage is now maintained by Hippo Camp Software and not Red Gate Software as was originally stated.

If you know me, you might well suspect this post is about some of the idiots I know, but it is not, this is entirely about some of the tools I use in day-to-day development. This is by no means an exhaustive list, nor is it presented in any particular order. However, assuming you are even a little bit like me as a developer, you will see a whole bunch of things you already use, but hopefully there is at least one item that is new to you. If you do find something new and useful here, or you have some suggestions of your own, please feel free to post a comment.

OzCode

OzCode is an add-in for Visual Studio that provides some debugging super powers like collection searching, adding computed properties to objects, pinning properties so that you don't have to go hunting in the object tree, simpler tracepoint creation, and a bunch more. I first tried this during beta and was quickly sold on its value. Give the 30-day trial a chance and see if it works for you.

Resharper

This seems to be a staple for most C# developers. I was a late-comer to using this tool and I am not sure I like it for the same reasons as everyone else. I actually love Resharper for its test runner, which is a more performant alternative to Visual Studio's built-in Test Explorer, and the ability to quickly change file names to match the type they contain. However, it has a lot of features, so while this is not free, give the trial a chance and see if it fits.

Web Essentials

Another staple for many Visual Studio developers, Web Essentials provides lots of support for web-related development including enhanced support for JavaScript, CSS, CoffeeScript, LESS, SASS, MarkDown, and much more. If you do any kind of web development, this is essential1.

LinqPad

I was late to the LinqPad party, but gave it a shot during Ann Arbor Give Camp 2013 and within my first hour or two of using it, dropped some cash on the premium version (it is very inexpensive for what you get). Since then, whether it is hacking code or hacking databases, I have been using LinqPad as my standard tool for hacking.

For code, it does not have the overhead of creating projects and command line, WinForms or WPF wrapper tools that you would have to do in Visual Studio. For databases, LinqPad gives you the freedom to use SQL, C#, F# or VB for querying and manipulating your database as well as support for many different data sources beyound just SQL Server, providing an excellent alternative to SQL Management Studio.

LinqPad is free, but you get some cool features if you go premium, and considering the sub-$100 price, it is totally worth it.

JustDecompile

When Red Gate stopped providing Reflector for free, JetBrains and Telerik stepped up with their own free decompilers for poking around inside .NET code. These are often invaluable when tracking down obscure bugs or wanting to learn more about the code that is running when you did not write it. While JetBrains' dotPeek is useful, I have found that JustDecompile from Telerik has a better feature set (including showing MSIL, which I could not find in dotPeek).

Chutzpah

Chutzpah is a test runner for JavaScript unit tests and is available as a Nuget package. It supports tests written for Jasmine, Mocha, and QUnit, as well as a variety of languages including CoffeeScript and TypeScript. There are also two Visual Studio extensions to provide Test Explorer integration and a handy context menu. I find the context menu most useful out of these.

Chutzpah is a great option when you cannot leverage a NodeJS-based tool-chain like Grunt or Gulp, or some other non-Visual Studio build process.

CodeLineage

CodeLineage is a free Visual Studio extension from Hippo Camp Software2. Regardless of your source control provider, CodeLineage provides you with a simple interface for comparing different points in the history of a given file. The simple interface makes it easy to select which versions to compare. I do not use this tool often, but when I need it, it is fantastic.

FileNesting

This Visual Studio extension from the developer of Web Essentials makes nesting files under one another a breeze. You can set up automated nesting rules or perform nesting manually.

I like to keep types separated by file when developing in C#. Files are cheap and it helps discovery when navigating code. However, this sometimes means using partial classes to keep nested types separate, so to keep my solution explorer tidy, I edit the project files and nest source code files. I also find this useful for Angular directives, allowing me to apply the familiar pattern  of organizing code-behind under presentation by nesting JavaScript files under the template HTML.

Whether you have your own nesting guidelines or want to ensure generated code is nested under its corresponding definition (such as JavaScript generated from CoffeeScript), this extension is brilliant.

Switch Startup Project

Ever hit F5 to debug only to find out you tried to start a non-executable project and have to hunt for the right project in the Solution Explorer? This used to happen to me a lot, but not since this handy extension, which adds a drop down to the toolbar where I can select the project I want to be my startup project. A valuable time saver.

MultiEditing

Multi-line editing has been a valuable improvement in recent releases of Visual Studio, but it has a limitation in that you can only edit contiguous lines at the same column location. Sometimes, you want to edit multiple lines in a variety of locations and with this handy extension, you can. Just hold ALT and click the locations you want to multi-edit, then type away.

Productivity Power Tools

Productivity Power Tools for Visual Studio have been a staple extension since at least Visual Studio 2008. Often the test bed of features that eventually appear as first class citizens in the Visual Studio suite, Productivity Power Tools enhances the overall Visual Studio experience.

The current version for Visual Studio 2013 provides support for colour printing, custom document tabs, copying as HTML, error visualization in the Solution Explorer, time stamps in the debug output margin, double-click to maximize and dock windows, and much more. This is a must-have for any Visual Studio user.

  1. yes, I went there []
  2. though it was maintained by Red Gate when I first started using it []