Author:


Introducing Rubicant – Part 3 – The inner workings

Posted by – January 22, 2009

Don’t forget to check out Part 1 and Part 2.

Rubicant basically has 4 main parts, as mentioned in the first part of this series. They are as follows:

The CscTask

The CscTask is used for compiling C# files. It’s usage is like:

   1: CscTask.new(:task_name => :dependencies) do |csc|
   2:   csc.target = 'library'
   3:   csc.references = FileList["libs\*.dll"]
   4:   csc.out = "hello_world.exe"
   5:   csc.debug = "full"
   6:   csc.files = FileList["src/**/*.cs"]
   7: end

target: Any target that the csc compiler takes (exe, winexe, library, etc)

references: The list of assemblies that are referenced during compilation

out: The output filename

debug: if this is set(to anything), the compiler will be passed /debug:full to create debugging information

files: The list of files to be compiled

CscTask also has a shortcut that can be accessed as follows:

   1: csc(name, dependencies, opts)
   2:  
   3: ex:
   4: csc :name, [:dependencies], { :target => 'library',
   5:                               :references = FileList["libs\*.dll"],
   6:                               :out = "hello_world.exe",
   7:                               :debug = "full",
   8:                               :files = FileList["src/**/*.cs"] }

 

The MBUnit Helper

The MBUnit helper is used to run tests using mbunit v2. It is used as follows:

   1: mbunit(mbunit_dir, test_dir, test_files, opts={})
   2:  
   3: ex:
   4: mbunit("/path/to/mbunit/dlls",
   5:         FileList["/test/dlls/test.dll"],
   6:         {:working_dir => "/dir/to/run/tests/in",
   7:          :assembly_path => FileList["/assemblies/to/include/*.dll"],
   8:          :report_folder => "sets /rf:",
   9:          :report_name_format => "sets /rnf:",
  10:          :report_type => "sets /rt:",
  11:          :show_reports => "sets /sr:",
  12:          :transform => "sets /tr:",
  13:          :filter_category => "sets /fc:",
  14:          :exclude_category => "sets /ec:",
  15:          :filter_author => "sets /fa:",
  16:          :filter_type => "sets /ft:",
  17:          :filter_namespace => "sets /fn:",
  18:          :verbose => "sets /v{optionvalue}",
  19:          :shadow_copy => "sets /sc:" }

For a complete listing of the mbunit command line options, please visit http://docs.mbunit.com/help/html/gettingstarted/MbUnitConsoleRunner.htm.

This runs the tests in test_files in the test_dir with the dlls from mbunit_dir using the options in opts. Currently, this will physically copy the minimum required mbunit dlls and mbunit.cons.exe to the test dir, run the tests and then remove the files.

The CopyFiles Task

The copy files task will copy files from one directory to another, while maintaining the folder structure.

   1: CopyFiles.new(:name) do |cf|
   2:   cf.base_dir = "/some/dir"
   3:   cf.file_globs = ["**/somefiles/*.cs", **/otherfiles/*.cs"]
   4:   cf.target_dir = "/another/dir"
   5:   cf.excludes = ["AssemblyInfo.cs"]
   6: end

base_dir: The base directory to start copying files from

file_globs: The globs of files to be copied from base_dir

target_dir: The target directory to place the files in

excludes: (Optional) list of files to be excluded from the copy.

The Expand Template File Task

Usage is:

   1: expand_template(template, output_file)

This will read in the file specified by template and expand it out and write it to the location of output_file.

WARNING: I am fairly certain that the only reason this is working right now for me is because I use configatron, which is accessed as a singleton. It is entirely possible that variables declared in your build script will not be accessible during template expansion. I will be testing this in the near future, however.

Framework Selection

Currently, only the .Net 2.0 and .Net 3.5 frameworks are configured. .Net 3.5 is the selection by default. However, you can choose which framework you want to use by adding framework={framework} in the build line. For example:

   1: rake deploy_local framework=net20

This will run the deploy_local task in the default rakefile using the .Net 2.0 framework.

Valid framework values are:

net20 – .Net 2.0

net35 - .Net 3.5

These frameworks are discovered using the registry, so you shouldn’t have to put in the location of your csc.exe file.

What else?

Well, that’s about all it really does right now. The rest is just built in rake and ruby goodness. I would like to add msbuild support for those that are building WPF apps. I would also like to add some nunit support, as well as some support for other things like easy creation of assemblyinfo.cs files and possibly some deployment tasks for iis7. Who knows. We’ll see how I like things and if I really take to using this (I think I will).

Introducing rubicant – Part 2 – A sample script

Posted by – January 22, 2009

Update: There is also a Part 1 and a Part 3.

Alright, so here is a sample build script for rubicant. First you will have to get rubicant installed. To do that, you need to get the source from https://rubicant.googlecode.com/svn/trunk/. I believe the username is rubicant-read-only.

In the root directory type:

   1: E:\projects\rubicant>rake gem
   2: (in E:/projects/rubicant)
   3: c:/ruby/lib/ruby/gems/1.8/gems/rake-0.8.3/lib/rake/gempackagetask.rb:13:Warning:
   4:  Gem::manage_gems is deprecated and will be removed on or after March 2009.
   5: mkdir -p pkg
   6: WARNING:  no rubyforge_project specified
   7: WARNING:  RDoc will not be generated (has_rdoc == false)
   8: WARNING:  deprecated autorequire specified
   9:   Successfully built RubyGem
  10:   Name: Rubicant
  11:   Version: 0.0.1
  12:   File: Rubicant-0.0.1.gem
  13: mv Rubicant-0.0.1.gem pkg/Rubicant-0.0.1.gem
  14:  
  15: E:\projects\rubicant>

Now you’ve got the gem built, you just need to install it:

   1: E:\projects\rubicant>gem install pkg\Rubicant-0.0.1.gem
   2: Successfully installed Rubicant-0.0.1
   3: 1 gem installed
   4:  
   5: E:\projects\rubicant>

 

There. Now for a test application. Suppose we’ve got 3 projects that make up a console app. The UI, the Engine (I KNOW) and the Tests. They look like:

solution

For now, let’s ignore the internal workings and focus on building it.

The build script looks like this:

   1: require 'rubicant'
   2: require 'configatron'
   3: include Rubicant
   4:  
   5: BASE_DIR = File.expand_path(".")
   6: SRC_DIR = "#{BASE_DIR}/src"
   7: SRC_APP_DIR = "#{SRC_DIR}/app"
   8: SRC_TEST_DIR = "#{SRC_DIR}/test"
   9: CONFIG_DIR = "#{BASE_DIR}/config"
  10: BUILD_DIR = "#{BASE_DIR}/build"
  11: DEPLOY_DIR = "#{BASE_DIR}/deploy"
  12: TOOLS_DIR = "#{BASE_DIR}/tools"
  13: MBUNIT_DIR = "#{TOOLS_DIR}/mbunit"
  14: RHINO_DIR = "#{TOOLS_DIR}/rhino"
  15:  
  16: UI_SOURCES = FileList["#{SRC_APP_DIR}/Rubicant.Test.App.UI/**/*.cs"]
  17: ENGINE_SOURCES = FileList["#{SRC_APP_DIR}/Rubicant.Test.App.Engine/**/*.cs"]
  18: TEST_SOURCES = FileList["#{SRC_TEST_DIR}/**/*.cs"]
  19:  
  20: #### Build Initialization
  21: task :initialize_build do
  22:     rm_rf BUILD_DIR if File.exists?(BUILD_DIR)
  23:     mkdir_p BUILD_DIR
  24:     rm_rf DEPLOY_DIR if File.exists?(DEPLOY_DIR)
  25:     mkdir_p DEPLOY_DIR
  26: end
  27:  
  28: #### Loading Properties
  29: task :load_local_properties do
  30:     configatron.configure_from_yaml("local.properties.yml")
  31: end
  32:  
  33: task :load_test_properties do
  34:     configatron.configure_from_yaml("test.properties.yml")
  35: end
  36:  
  37: #### Deployment Targets
  38: task :deploy_local => [:load_local_properties, :deploy]
  39:  
  40: task :deploy_test => [:load_test_properties, :deploy]
  41:  
  42: task :deploy => [:test, :expand_app_config] do
  43:     cp FileList["#{BUILD_DIR}/{hello.exe,engine.dll}"], DEPLOY_DIR
  44: end
  45:  
  46:  
  47: #### Compile Targets
  48: csc :compile, [:initialize_build, :compile_engine], {:files => UI_SOURCES,
  49:                                                      :target => "exe",
  50:                                                      :out => "#{BUILD_DIR}/hello.exe",
  51:                                                      :references => FileList["#{BUILD_DIR}/*.dll"] }
  52:                 
  53: csc :compile_engine, [], {:files => ENGINE_SOURCES,
  54:                           :target => "library",
  55:                           :out => "#{BUILD_DIR}/engine.dll"}
  56:                 
  57: #### Testing Targets                
  58: task :test => [:compile_tests, :run_tests]
  59:  
  60: csc :compile_tests, [:compile], {:files => TEST_SOURCES,
  61:                                           :target => "library",
  62:                                           :out => "#{BUILD_DIR}/tests.dll",
  63:                                           :references => FileList["#{BUILD_DIR}/**/*.{dll,exe}", "#{RHINO_DIR}/*.dll", "#{MBUNIT_DIR}/*.dll"]}
  64:  
  65: task :run_tests do
  66:     mbunit(MBUNIT_DIR, BUILD_DIR, FileList["#{BUILD_DIR}/tests.dll"], {:assembly_path => FileList["#{BUILD_DIR}/engine.dll", "#{RHINO_DIR}/*.dll"].to_a})
  67: end
  68:  
  69:  
  70: #### App.config expansion
  71: task :expand_app_config do
  72:     expand_template "#{CONFIG_DIR}/App.Config.template", "#{DEPLOY_DIR}/hello.exe.config"
  73: end

The point of this build file is to be able to churn out two different builds based on two different sets of properties. This is based off of my builds that I do at work where we need to deploy and test in a test environment before going into production. It would be as simple as adding a production.properties.yml and a deploy_production target to simulate this fully in this script.

So basically, we call deploy_test (or deploy_local), which in turn loads the test properties, and then the deploy task.

Deploy calls the test task, which builds the app, builds the tests, runs the tests. If any tests fail, the build will fail here, making sure we don’t deploy any code that doesn’t pass tests.

Finally, we expand our app.config in a way suitable for the environment we’re going into.

Finally, run the executable to see that it worked!

   1: E:\projects\Rubicant.Test.App>deploy\hello.exe
   2: Hello, World! (Test Version)
   3:  
   4: E:\projects\Rubicant.Test.App>

 

You can download the source from http://blog.beigesunshine.com/wp-content/uploads/2009/01/rubicanttestapp.zip and try it out for yourself. The default rakefile goes to an exe and an assembly. You can also run both deploy_local and deploy_test and create a single exe file by using rake -f rakefile_single_exe.rb deploy_local.

Coming up, a post on some of the specifics of rubicant.

Introducing rubicant

Posted by – January 15, 2009

Update: Don’t forget to check out Part 2 and Part 3.

In previous posts I have mentioned that I think that there might be a better way to automate builds than NAnt. I also mentioned that I had looked at a few of them and been mostly underwhelmed. I’ve spent a large amount of time building a process for builds that works well for me and none of them seemed to erase my pains.

I also mentioned that I would be working on some items that may even drive some content to this blog, among other things. Today, I introduce the fruits of my labour.

Please note that this is NOT recommended for any sort of production environment. It is currently at best a way to try out Rake on .Net projects.

What is rubicant?

rubicant is my own personal set of tasks that sit on top of rake, a rubyish interpretation of make. I’ve used ruby for some scripting in the past, and also used rake in a rails app that I developed. I felt that the combination of both would alleviate some of the pains that I (and I’m pretty sure I’m not alone here) feel when I use NAnt.

I was admittedly scared to even try building my own set of tasks, and actually didn’t even know where to start. I kept rolling the idea around. One day I was going to start doing it now. Then the next I wasn’t. As a father of young children my spare time is very limited and very few and far between, especially for something that would demand so much of it.

And then the I started coming across others experimenting with exactly what I was talking about. First it was a post by Dave Laribee, as well as another post in his comments. And now as I read over them again, I’m seeing that there’s more people feeling like I do. I started to google and found some great posts by Jay Fields and to a lesser extent one by Martin Fowler.

Anyway, in my looking it seemed like no one had actually put out a reusable library that anyone could just pick up and automatically compile a project within 5 minutes.

And thus, with some much needed inspiration from the above sources, rubicant was born.

What isn’t rubicant?

Well written for one thing. Take a look at my tests and they’re enough to make someone blow a gasket :D (I kid, I LOVE his twitter rants) I started writing them thinking I knew what I was doing and let me clear something up for you. At the time, I had a greatly misguided view on BDD/Specification testing. Either way, it’s still got my code covered and has helped to drive out some of the design, especially when loading framework information.

Another thing it is not is a complete solution. I had 4 goals in functionality that I wanted. They were:

    1. Build C# code
    2. Test C# code (with MBUnit)
    3. Copy selected files in a meaningful hierarchy
    4. Template expansion using configatron to allow for easy configuration swapping.

Why rubicant?

First off, automated builds are the only thing that I feel I truly have a grasp on. I feel comfortable enough in myself and my process that I could come up with something useful. I don’t think of myself as a guru, but I do know that I have a set of build scripts at work that are robust and involved while trying to stay (somewhat simple). In other words, I don’t consider myself a guru, but I do feel I have a grasp on the subject.

I was also feeling too much pain with NAnt. As well, I didn’t feel that any of the other solutions out there really felt like what I was looking for. I was also looking for a learning project in ruby. I wanted to try driving out a design via testing using ruby. A lot of things. Either way, I felt like I wanted to do something for myself, but that also might provide some sort of benefit to the community, even if it just ended up as a failed attempt. In a sentence: I wanted to try and provide SOMETHING back to a community that I feel has given me so much.

Even if this ends in failure, it’s been exactly the experience that I’ve wanted thus far, and though I’m sure I’m in for some rough waters ahead, I think that it will continue to drive me to learn, improve and better myself. Okay, so there is definitely some selfishness there, but hopefully you can forgive me in the name of Continuous Improvement, even if it’s my own.

How do I get it? How do I use it?

Well, if you want to get it, you can go to the project site on google code and download the source. There are instructions there on how to install it. As for how to use it… stay tuned for a sample project and build file. Hopefully very soon.

 

Update: Don’t forget to check out Part 2 and Part 3.

Procrastination, we meet again!

Posted by – December 20, 2008

I told myself I would do a whole lot more writing than I’ve been doing. I’ve even got ideas of things I would like to write on! Honest. Anyway, between Christmas, kids and a project (that’s related to this blog!) that I’ve been working on, I haven’t had a lot of time to sit down and focus.

So to my whopping 0 subscribers, just you wait! There will be content. Oh yes. There will be content.

Humor in Canadian Politics

Posted by – December 5, 2008

 

I’m not typically one to outright throw my beliefs in the faces of others just to be noticed, and that isn’t the intent here either. For those of you who haven’t heard or don’t know, Canada has a parliamentary form of government which you can kind of boil down to the fact that it’s possible for someone to run the government, but without a clear majority. This week in Canada, the left wing parties have decided to try and form a Coalition Government to overthrow the Conservatives.

As well, some of you may notice the reference in my blog to The Dead Milkmen a humorous punk band from the 80′s and 90′s.

Well a friend of mine and I have taken this opportunity to show not only a tribute to the Milkmen, but also to make light of the situation in the country. So here, for all posterity I give unto you my version of Beach Party Vietnam:

Bloc Party Quebecois

Duceppe and Bouchard with Michaëlle Jean
When Duceppe got a letter from Mr. Dion
Said get Layton and everyone
We’re gonna start a co-ali-tion.

With the Bloc Party Quebecois
Parle anglais? Je ne c’est pas!
Seperatists eating foie gras
It’s a Bloc Party Quebecois!

Hey Duceppe! Aren’t you gonna try and be PM?
I’m afraid I can’t do that Bouchard.
Why not?
Because I don’t have any support in english Canada!!!
(AAAAAAAAAAAAAAAAHHHHHHHHHHH!)

Bloc Party Quebecois
Parle anglais? Je ne c’est pas!
Seperatists eating foie gras
It’s a Bloc Party Quebecois!

Duceppe he wants Harpers head
Harper wants the Bloc dead.
Hangin on the east side
Gonna be some party genocide

It’s a Bloc Party Quebecois
Parle anglais? Je ne c’est pas!
Seperatists eating foie gras
It’s a Bloc Party Quebecois!

YEAH!!!

There are no stupid questions

Posted by – December 5, 2008

 

Today I was suddenly reminded of a question I saw somewhere a couple weeks back. I wasn’t going to admit it at first, but it was on Stack Overflow. I actually went looking for the question, but can’t seem to find it, so here’s my version of the story from memory.

The question basically said that after every commit to a code base, it would trigger a build on their build server. The build generated a file (I think it was called revision.txt) that was tagged with the current revision number, and then checked back into source control, which would then trigger a build, which would generate a file……. and so on.

I was so focused on the fact that they would be generating something that could be retrieved at any point in time from the repository that I failed to see the value of what was really being asked. I the fact that you would create a file with a revision number, and check it into the repository, effectively nullifying that revision number was so consuming for me that I didn’t stop to think that it might actually be helpful to not build on every commit.

Then this morning I was working on some test documentation for a deployment that we’re doing soon. As I made changes and checked them into the repository, I kept triggering builds. Then it hit me. I realized that there’s really no reason why a test doc that has nothing to do with a the build. I mean, in this case, the build doesn’t take long, but we have some pretty big projects here that can really hit our build server hard (which causes emails to be sent out to our server admins).

It didn’t take me long to find the Filtered Source Control Block and update our configuration to use it.

But it got me thinking. Though I don’t fully agree with the process being described in the original question, I was so focused on what was wrong that I completely missed out on learning about what was actually a valid, useful and soon-to-be relevant feature in my build server.

More on builds

Posted by – November 25, 2008

 

Here I am updating a build script and finding myself thinking about this mornings post a LOT. If a tool like ClipX can greatly increase my productivity simply because of how much multiple copy/pasting I have to do just to use a templated assemblyinfo.cs file, then something is not right.

NAnt completely removes the Don’t from Don’t Repeat Yourself, unless you want to lose readability like I stated this morning.

Oh, and ClipX really is a great tool. I especially love the sticky plugin, as I really hate typing email addresses and don’t use my browser’s password manager/autoforms. Quick ctrl-shift-v then a and I have my entire massive email address put in.

Building’s the Foundation

Posted by – November 25, 2008

 

Let me get this off my chest. I think about Build Scripts all the time. I spent the better part of the first 6 months at my current job migrating old legacy .Net 1.1 web apps from  CVS to .Net 2.0 and Subversion. Part of that included migrating the projects from CVS to SVN, then taking the old projects and migrating those into our current directory structure for projects. After that, I had to template the config files and create build scripts that could build a local, test or production version of an app with a single command.

During the course of this, I used PowerShell, Ruby and of course, NAnt.

I found that, like many things, I was able to find some things I loved about all of them. And lots of things I hated about most of them. PowerShell, for one, has some great ideas in it. It’s truly a good idea. I love the idea of being able to leverage the .Net Framework from my scripts. It really is a good idea. But after the few scripts that I wrote in PowerShell, I don’t think that I could use it again. I found the syntax either annoying or clunky the whole time. Especially once I started writing the scripts in Ruby.

Now Ruby I have some experience in as I’ve done a bit of Rails development. Lots of the notations I like. I have some difficulty in using a dynamic language at times, most notably I find myself missing method signatures that are strongly typed. However, the annoyances are small, and mostly come in the form of me running into issues with working with the file system. I think those annoyances mostly come from me not fully understanding some of the intricacies of working with the filesystem on windows with ruby.

I find the biggest difference between the two is how easy it is to use Ruby from within a CygWin Bash shell. I’ve been a longtime linux user, and actually my first unix-like operating system that I used at home was FreeBSD. Because of FreeBSD, I was a long time user of tcsh. In fact, it was less than a year ago that I finally made the move over to bash. Either way, both of these shells provide power, ease of use and so many advantages that I can’t believe that Microsoft doesn’t have them in any of it’s shells. I mean seriously, how does anyone live without a searchable history in a command prompt?

And this brings us to NAnt. I was in love with NAnt when I first started. It was great to use, simple and it could do so much. But I started to find myself hitting situations where things would become very murky and difficult to keep track of where things were happening, especially when I tried to make things generic so they could be called in many places. For example, here is how a template file is expanded in our code:

   1: <target name="expand.template.file">
   2:     <copy file="${template.file}.template" tofile="${template.file}" overwrite="true">
   3:         <filterchain>
   4:             <replacetokens>
   5:                 ....lots of tokens...
   6:             </replacetokens>
   7:         </filterchain>
   8:     </copy>
   9: </target>

 

But where does ${template.file} get set? Why, the line before we call expand.template.file of course!

   1: <property name="template.file" value="${some.dir}\app.config"/>
   2: <call target="expand.template.file" />

 

I just find that this can be confusing, especially to newcomers who don’t know which targets act as functions. I know that you could do a search through the code and find it, but it’s just not as clean or explicit as something like:

   1: expandTemplate(filename)
   2:  
   3: def expandTemplate(filename)
   4:     ...expand in here...
   5: end

 

So I think that you can see where I’m going with this. After a while of doing this, I started to think a lot about Rake. After all, I had used it in Rails projects previously. As you can tell, I’m quite a fan of Ruby. After a while, things began to cool off. I had gotten almost all of our projects converted and I wasn’t writing build files as much anymore. But I kept on thinking about it. Recently, I’ve been writing build files again. I’ve also been reading that I’m not the only person who feels this way.

I’ve noticed a few projects that seem to be reaching for what I want. There’s Boo Build System (and yes, it is shortened to BooBS. Nice work Ayende), PSake (which JP seems to have picked up) and then there’s Rake. Rake seems to be the only one that isn’t geared towards some sort of .Net problem (not that it can’t). It turns out that though there was a lot of hype around boo a while back, I just don’t think it’s something I’m up for learning just yet. And as for PSake, I downloaded the source and nothing against James (it’s not his fault, it’s the syntax!) I barely made it through the first PS1 file before my head hurt and I remembered why I stopped writing PowerShell scripts in the first place.

That leaves me with Rake. And it seems like I’m not the only one. The only difference is that I would absolutely love to see a Gem built with some custom .Net tasks for rake. This is something that I’ve been seriously contemplating putting some time into, but haven’t fully explored yet. Most notably, I would like to take the syntax of:

   1: require 'lib/nunittask'
   2:  
   3: Rake::NUnit.new do |nunit|
   4:   nunit.library = "foo.dll"
   5: end

 

And replace it with something along the lines of:

   1: require 'lib/nunittask'
   2:  
   3: nunit :test, :library => 'foo.dll', :depends => [:load_properties, :compile]

 

I get the feeling that this could be wrapped up in a function which could use Hash which could hide away the nastiness of Rake::Task.new do |task| block and take these scripts to an entirely new level. I’m not entirely sure how the naming would work, but I’m sure it would.

After writing this, I think I’m going to start taking a much closer look. Has anyone heard of anything like this in the works/already released?

It’s not supposed to be inflammatory or controversial

Posted by – November 19, 2008

 

I tend to be an opinionated individual. As such, when I present (or defend) my opinions, I tend to go out of my way to push my opinion as the correct one. I may go as far as to insinuate that others are wrong. This tends to get mixed feelings from a lot of people. Some people just think I’m asserting myself. Others think I’m a know it all. Others just think I’m a plain jerk. There maybe some truth in all three.

Sometimes it just ends up that things work one way for me, and another way for someone else (See my last post). There’s nothing I can do when it comes to that. People are different. Just because something is wrong for me, doesn’t mean it’s wrong for everyone.

I do however, realize that sometimes I’m wrong. Consider this my open invitation to all you (nonexistent) readers out there. If you think I’m wrong, incorrect or just plain out to lunch. Please call me out. Don’t just tell me I’m wrong though. If you can’t back yourself up, then don’t bother. Tell me why I’m wrong. Make me defend myself, or it’s just not worth it.

If there’s one thing I’ve found in my time on the internet, it’s that if you assert yourself enough and just act like you’re right, people will listen to you. Most people don’t have the will to stand up to someone who thinks they’re right.

I hope you do.

If programmers are typists first, then I’d better get a Typing Tutor

Posted by – November 18, 2008

 

This afternoon I found that Jeff Atwood has once again made another post that left me shaking my head. Kind of like a car wreck, I just couldn’t look away. This evening, Jimmy Bogard posted a response. I have to say that I agree with Jimmy wholeheartedly.

The only exception to this rule as I see it is that you can’t be a hunt and peck typist. I don’t care how much code you write, if you have to watch your hands fingers while you’re writing code, you probably could benefit from a round or two of QWERTY Warriors. I’ve worked with hunt and peck typists and it can be infuriating to pair program with them, but I’m admittedly brash and impatient. It’s something that I’ve actually been working on.

Anyhow, I’m a C# coder. C# isn’t exactly known for it’s brevity, and neither are some of my class and method names. However, we developers are a crafty bunch. If there’s a way for us to do things quicker, better or faster, you can rest assured that someone has attempted to solve the problem with some sort of little app or program. Tools like Intellisense, Keyboard Shortcuts and especially ReSharper are all ways to help us reduce the time and number of keystrokes required to do things. In fact, I’d say that 90% of the code I write, I don’t even type entire words. I write I type u-s-ctrl-space and I have userService. I don’t care if you type 84 wpm or 20 wpm: 4 keystrokes is always faster to type than 11.

Also, I don’t see too many typing tests that emulate  string Username { get { return username; } } or for (int i = 0; i < 10; i++) very well. But even that is nearly a moot point. A tool like ReSharper can add a read only property in just a few keystrokes, and with its live templates the for loop almost writes itself. Coding and the associated thinking and planning involved aside, we should be the users of tools first and typists a distant second.

Basically, what I’m saying is that if you’re a C# coder (isn’t StackOverflow written in C#?) and you are writing code in a manner that requires you to be a typist first and a programmer second, you’re doing it wrong. You’re either writing some pretty crazy legacy code (who here hasn’t written a function with a couple hundred lines in it?) or you’re the victim of a problem that’s already been solved.

History has already shown that Jeff is quite happy being a victim.