Blog your code using Google SyntaxHighlighter

Google SyntaxHighlighter is a simple tool that allows bloggers to easily display code in a format that is familiar end users. The tool renders the code in a very consumable fashion that includes colored syntax highlighting, line highlighting, and line numbers.

/*

This is an example of how Google

SyntaxHighlighter can highlight and display syntax

to you, the end user

*/

public void HelloWorld()

{

  // I have some comments

  Console.WriteLine("Hello, World!");

}

It is purely a client-side tool, as all of the processing is done strictly within the browser through JavaScript. There is no server-side processing. Since it is all JavaScript, you don't need special Copy/Paste plugins and macros installed to your favorite IDE or your blog authoring tool. (I am leery of random plugins and installing them into the software that I use to feed my family.) To including code in your blog post, copy your code from Visual Studio, Notepad, Flash, Firebug, or any tool that displays text, and paste it in to your post. As of v1.5.1, Google SyntaxHighlighter supports C, C++, C#, CSS, Delphi, HTML, Java, JavaScript, PHP, Pascal, Python, Ruby, SQL, VB, VB.NET, XML, XSLT, and all of this is just what comes out of the box.

Setting Up SyntaxHighlighter

To get SyntaxHighlighter running on your blog, download the latest version of the RAR archive and extract the code. The archive contains a parent folder, dp.SyntaxHighlighter, with three child folders:

dp.SyntaxHighlighter

  \Scripts         //Production-ready (Compressed) scripts

  \Styles          //CSS

  \Uncompressed    //Human-readable (Uncompressed/Debug) scripts

Once the archive is extracted, upload dp.SyntaxHighlighter to your blog. Feel free to rename the folder if you like, though I did not. It is not necessary to upload the Uncompressed folder and its files; they are best used for debugging or for viewing the code, as the files in the Scripts folder have been compressed to reduce bandwidth by having most of their whitespace removed.

After you have uploaded the files, you will need to add script and style references to your site's HTML. This is code is not for your posts, but rather for your blog template. In DasBlog, I place this code in the <HEAD> block of my homeTemplate.blogtemplate file. Remember to change the file paths to match the path to where you uploaded the code.

<link type="text/css" rel="stylesheet"

  href="dp.SyntaxHighlighter/Styles/SyntaxHighlighter.css"></link>

<script language="javascript" src="dp.SyntaxHighlighter/Scripts/shCore.js"></script>

<script language="javascript" src="dp.SyntaxHighlighter/Scripts/shBrushCSharp.js"></script>

<script language="javascript" src="dp.SyntaxHighlighter/Scripts/shBrushXml.js"></script>

<script language="javascript">

window.onload = function () {

  dp.SyntaxHighlighter.ClipboardSwf = 'dp.SyntaxHighlighter/Scripts/clipboard.swf';

  dp.SyntaxHighlighter.HighlightAll('code');

}

</script>

To make the tool most efficient, including minimizing the code download by the client browser, highlighting is only enabled for the languages that you specify. The highlighting rules for each language is available through a file referred to as a Brush. The code sample above enables only C# and XML/HTML by including the core file, shCore.js, the C# brush, shBrushCSharp.js and the XML/HTML brush, shBrushXml.js. A unique brush file is available for each of the supported languages, and only the core file is required. These brushes are located in your Scripts directory (the human-readable version is in the Uncompressed folder). Include only the brushes that you like; if you forgot a language brush, the code will still display on your page, but as unformatted text.

<!-- Unformatted HTML Code / No Brush -->

<p id="greeting">Hi, mom & dad!</p>
<!-- Formatted HTML Code -->

<p id="greeting">Hi, mom & dad!</p>

Making SyntaxHighlighter Go

Now that the application is deployed to the site, how does it get applied to a post? Paste the code into the HTML view of your post, inside of a <PRE> tag. Create a name attribute on your tag with a value of code, and a class attribute set to the language and options you are using.

<pre name="code" class="c-sharp">

  public void HelloWorld()

  {

    Console.WriteLine("Hello, World!");

  }

</pre>

One catch is the code must be first made HTML-safe. All angle-brackets, <tag>, must be converted to their HTML equivalent, &lt;tag&gt;, as well as ampersands, & to &amp;. I also find it helpful if your code-indentation uses two-spaces, rather than tabs.

<!-- Pre-converted code -->

<p>Hi, mom & dad!</p>
<!-- Converted code -->

<pre name="code" class="html">

  &lt;p&gt;Hi, mom &amp; dad!&lt;/p&gt;

</pre>

The class attribute is made up of both language and option aliases. These aliases consist of one language followed by your desired options, all in a colon delimited list.

class="language[:option[:option[:option]]]"

The value of language is any of SyntaxHighlighter's defined language aliases, such as c#, csharp, or c-sharp for C#, or rb, ruby, rails, or ror for Ruby. See: full list of available languages.

Options allow for such things as turning off the plain text / copy / about controls (nocontrols), turning off the line number gutter (nogutter), or specifying the number of the first line (firstline[n]). A JavaScript code block with no controls header, and starting the line numbering at 34 would have a class attribute value of class="js:nocontrols:linenumber[34]". See: full list of available options.

Extending SyntaxHighlighter

Because Google SyntaxHighlighter is entirely in JavaScript, you have access to all of the code. Edit it however you like to suit your needs. Additionally, brushes are very easy to create, and include little more than a list of a highlighted language's keywords in a string and an array of language aliases. Creating a brush for ActionScript or QBasic would not take much time. Language brushes exist in the wild for Perl, DOS Batch, and ColdFusion.

In a future post I plan on discussing Brush Creation in depth through creating a brush for ActionScript.

Comparing SyntaxHighlighter to Others

I am a fan of this tool, though that should be obvious considering it is what I use on this blog. I like how readable the code is, how extendable it is, and how easy it is to use. I don't like its compatibility--or lack thereof--with RSS; since all of the work is done in JavaScript, and RSS doesn't do JavaScript, there is no syntax highlighting, numbers, or options within a feed, though the code formatting is still maintained. Other tools, like the CopySourceAsHtml plugin for Visual Studio or Insert Code Snippet for Windows Live Writer convert your code into formatted HTML, where all of the syntax highlighting is applied through HTML attributes and embedded CSS. Their methods are much easier than SyntaxHighlighter, since there are no stylesheets or JavaScript files to include in your HTML, and you don't have to worry about making your code HTML-safe. Also, their method works in RSS feeds. However, there isn't the same level of control. Through SyntaxHighlighter's extendibility, I can theme my code views, such as if I wanted them to look like my personal Visual Studio theme. Through SyntaxHighlighter, I can also make changes at a later time, and those changes will immediately reflected in all past posts, whereas making modifications to the HTML/embedded CSS pattern is much more difficult.

Final Thoughts

I like CopySourceAsHtml in Visual Studio. I used it for years on this blog. But I code in more languages than VB.Net or C#, and the plugin isn't available within the Flash or LoadRunner IDE. I was also frustrated with pasting my code in, only to find that it was too wide for my blog theme's margins, and would have to go back to Visual Studio, change my line endings, and repeat the process. I'm sticking with Google SyntaxHighlighter. It works for all of my languages (as soon as I finish writing my ActionScript brush), and when my line endings are too long, I simply change my HTML. And in my HTML, my code still looks like code, rather than a mess of embedded style. I have to sacrifice RSS formatting, but as a presentation developer that is very particular about his HTML, I am glad for the customization and control.

URL Rewrite, Part 2: HTTP 301, Moved Permanently

A few months ago I switched my blogging engine from WordPress to DasBlog, and was left with a pile of broken post links. The WordPress format of formatting URLs, such as cptloadtest.com/?p=56, no longer applied; DasBlog has its own way of building the URL: cptloadtest.com/2006/05/31/VSNetMacroCollapseAll.aspx. Other people, with links to my posts on their own blogs, and search engines, with search results pointing to the old format, no longer directed people to the proper page. Fortunately, the old WordPress way directed users to the domain root, so they saw the main page instead of a 404, but what I really needed was a way to get users to the content they came for. But, I wanted a way that didn't involve customizing DasBlog code.

Part 1 discusses some client-side options for redirecting traffic. As a developer, I would only need to add some quick JavaScript or HTML to my pages to reroute traffic, but I wanted a better way. I wanted Google's links to be updated, rather than just for the link to correctly route. I want a solution that worked without JavaScript. I wanted a solution that didn't download the page twice, as any client-side processor would do. I wanted the HTTP 301.

HTTP 301, Move Permanently, is a server-side redirection of traffic. No client-side processing is involved. And Google recognizes that this is a permanent redirect, as it's name implies, so the Google result link is updated to the new URL. But since this is a server-side process, and I don't have full access to IIS settings with my hosting provider, I needed some code.

response.StatusCode = 301;

response.AddHeader("Location", "http://www.cptloadtest.com");

response.End();

You may have noticed that, unlike the title of this blog post, I did not use a URL rewrite. HTTP 301 (and 302) redirects are HTTP Response Codes that are returned to the client browser, and the client then requests the new URL. A URL Rewrite leaves the original URL in place, and renders a different page instead, without visibility to the client browser or end-user. If I were to URL rewrite my blog from page1.aspx to page2.aspx, the URL in your address bar would still list page1.aspx, even though the content was from page2.aspx. The end-user (and the search engine) never know about the URL for page2.aspx. However, with a HTTP redirect, the content and the address bar would both be page2.aspx.

I ran through Google to see if anyone had solved this problem in the past. I came across a Scott Hanselman post on HTTP 301, which mentions a fantastic drop-in redirect module by Fritz Onion. I was elated when I found this module, and it was very easy to implement. Drop the assembly into your application's bin, add a few lines into the web.config, and enjoy redirection bliss. The module also supports both HTTP 302 and HTTP 301 redirects through the "permanent" attribute in the redirection rules.

<?xml version="1.0"?>

<configuration>

  <configSections>

    <section name="redirections"

      type="Pluralsight.Website.XmlSerializerSectionHandler, redirectmodule" />

  </configSections>

  <!-- Redirect Rules -->

  <redirections type="Pluralsight.Website.redirections, redirectmodule">

    <!-- Wordpress Post Redirects //-->

    <add targetUrl="/default\.aspx\?p=86"

      destinationUrl="/2007/09/22/ManagingMultipleEnvironmentConfigurationsThroughNAnt.aspx"

      permanent="true" />

    <add targetUrl="/default\.aspx\?p=74"

      destinationUrl="/2007/02/09/Flash8DepthManagerBaffledByThoseWithoutDepth.aspx"

      permanent="true" />

    <add targetUrl="/default\.aspx\?p=72"

      destinationUrl="/2006/10/20/IE7Released.aspx"

      permanent="true" />

    <add targetUrl="/default\.aspx\?p=70"

      destinationUrl="/2006/10/17/ClearingFlashIDEWSDLCache.aspx"

      permanent="true" />

    <add targetUrl="/default\.aspx\?p=69"

      destinationUrl="/2006/10/10/CruiseControlNetV11ReleasedOct1.aspx"

      permanent="true" />



    <!-- ...More Redirects -->

  </redirections>

  <system.web>

    <httpModules>

      <add name="RedirectModule" type="Pluralsight.Website.RedirectModule, redirectmodule" />

    </httpModules>

  </system.web>

</configuration>

The entire implementation took only a few minutes. It seemed like it took longer to upload the changes to the blog than it did to make the local edits. The solution is also very clean, as it required no modification to the existing application beyond integrating the configuration blocks into the web.config. Blog traffic will now seamlessly redirect from links that use the old WordPress URL to post that use the new DasBlog URL. Search Engines also update their links, and the page ranking for each post isn't lost into the ether just because the URL changed. All is well with the world, again.

Next up: Part 3. URL redirection also plays a role in Search Engine Optimization. In Part 3, I will go over some ways that you can use HTTP redirects to improve your search engine listings, as well as discuss some improvements I made to Fritz Onion's redirect module in the name of SEO.

Technorati Tags: ,,

URL Rewrite, Part 1: HTTP 302, Temporarily Relocated

A few months ago I switched my blogging engine from WordPress to DasBlog. Though I do feel that WordPress is a more mature engine, with a more robust feature set and a better plug-in community, I wanted a site that was built on .NET. Being a .NET developer, I wanted something I could tinker with,  modify, and adjust to my liking.

Redirecting WordPress URL Format to DasBlog

One of the pain points of the switch was with the differences in how the two blogging engines generated their URLs. As an example, my post on the Collapse All macro for the Visual Studio Solution Explorer, originally written in WordPress, went from a URL of cptloadtest.com/?p=56 to cptloadtest.com/2006/05/31/VSNetMacroCollapseAll.aspx. A few sites, such as Chinhdo.com, link to the post's old URL, which without effort to put a redirect in place would return HTTP 404: File Not Found under the new engine.

Enter URL redirects. I needed a way to translate one URL into another. More specifically, since WordPress retrieves all of its posts by query string (using the 'p' key), I needed to translate a specific query string key/value pair into a URL. But, I didn't want to have to recompile any code.

There are a view client-side redirecting options available:

Meta Refresh

<meta http-equiv="refresh" content="0;url=http://www.cptloadtest.com/">

The Old-School HTML way of redirecting a page. Nothing but HTML is needed. Only access to the base HTML page is required. Place the above HTML within your <HEAD> tag, reformatting the content value with "X;url=myURL", where X is the number of seconds to wait before initiating the redirect, and myURL is the destination URL. Any browsers will obey Meta-Refresh, regardless of JavaScript's enabled setting, but the simple implementation brings with it simple features. Meta-Refresh will redirect any request the page, regardless of the query string, and there is no simple way to enable it only for the specific key/value query string pair. Because all WordPress requests are to the domain root--a single page--and referenced by query string, this would not work for my needs. If the old request was instead to a unique former page, such as /post56.html, I could go create a new copy of post56.html as just a stub, and have each page Meta-Refresh to the post's new location. But even if this did apply, it's too much work to create 56 stub pages for 56 former posts.

JavaScript Redirect

<script type="text/javascript">

<!--

window.location = "http://www.cptloadtest.com/"

//-->

</script>

This one requires JavaScript to work. Since the query string is on the domain root, the request is serving up Default.aspx and applying the query string to it. DasBlog doesn't observe the "p" query string key, so it will not perform any action against it, but the query string is still available to client-side scripts. I can add JavaScript code to perform regular expression matches on the URL (window.location), and upon match rewrite the old URL to the new and redirect. It's relatively simple to create new match patterns for each of my 56 posts, and I can place all of my new client-side code atop Default.aspx.

var oldPath = "/?p=56";

var newPath = "/2006/05/31/VSNetMacroCollapseAll.aspx";

if (document.URL.indexOf(oldPath) > 0)

{

  window.location.replace(document.URL.replace(oldPath, newPath));

}

However, since the patterns are in client-side code, they are visible to end-users who view source. Users will also see page-flicker, as the Default.aspx is served up using the old URL, only to be redirected and refreshed under the new URL; a side-effect of downloading the page twice is that my bandwidth is also doubled for that single request, since users downloaded the page twice.

What it all means

All of the options above result in functionality similar a HTTP 302, otherwise known as a Temporary Redirect. This class of redirect is meant for simple forwarding or consolidation that is either of temporary nature or part of intended functional implementation. An example of where this would be used is if after one page is finished processing, another should be returned, such as if authentication is complete on a login page and the client should be redirected to a home page or landing page. With a 302, the original page is still a valid page, and users should still go to it in the future, but under certain scenarios there is an alternate page should be used.

The alternative to a 302 is a HTTP 301, otherwise known as Moved or a Permanent Redirect. The 301 is for files which have permanently changed locations and come with an implied "please update your links" notice. The HTTP 301 is ultimately what I was looking for. cptloadtest.com/?p=56 is a defunct URL that will never again see light of day; users, web sites, and (most importantly) search engines should update their references to the new DasBlog format of the post's URL. Client-side coding doesn't have the ability to create an HTTP 301, so it was beginning to look like I may either have to modify DasBlog code to get my 301s or live without. But, I found a way; this site now has all of the 301 goodness I craved, while keeping the DasBlog code pure.

It's all about HTTP Modules.

In Part 2, I will go over how to use HTTP Modules to implement both HTTP 301 and HTTP 302 redirects, all with simply dropping a file into your application bin and adding a new section to your web.config. No compile required.

Stay tuned.

Unit Testing ActiveRecord Applications using Mock Databases

Recently, I was writing unit tests for a web application built on Castle ActiveRecord. My goal was to mock ActiveRecord's data store, rather than use a Microsoft SQL Server database for testing. SQL Server backing just would not fit my needs, where a mock data store would serve much better:

  • I did not want a SQL Server installation to be a requirement for me, the other developers, and my Continuous Integration server.
  • I wanted something fast. I didn't want to have to wait for SQL Server to build / tear down my schema.
  • I wanted something isolated, so the other developers, and my CI server, and I wouldn't have contention over the same database, but didn't want to have to deal with independent SQL Server instances for everyone.

Essentially what I wanted was a local, in-memory database that could be quickly initialized and destroyed specifically for my tests. The resolution was using SQLite for ADO.Net, using an in-memory SQLite instance. Brian Genisio has a fantastic write-up on mocking the data store for Castle ActiveRecord using this SQLite for ADO.Net. The post made my day, since I was looking for a way to do this, and he had already done all of the work <grin/>. I encourage you to read his post first, as the rest of this post assumes you have already done so.

Brian's post was a great help to me; I made a few enhancements to what he started to make it fit my needs even more.

My updated version of Brian's ActiveRecordMockConnectionProvider class:

using System;

using System.Collections;

using System.Data;

using System.Reflection;

using Castle.ActiveRecord;

using Castle.ActiveRecord.Framework;

using Castle.ActiveRecord.Framework.Config;

using NHibernate.Connection;



namespace ActiveRecordTestHelper

{

  public class ActiveRecordMockConnectionProvider : DriverConnectionProvider

  {

    private static IDbConnection _connection;



    private static IConfigurationSource MockConfiguration

    {

      get

      {

        var properties = new Hashtable

            {

              {"hibernate.connection.driver_class",

                "NHibernate.Driver.SQLite20Driver"},

              {"hibernate.dialect", "NHibernate.Dialect.SQLiteDialect"},

              {"hibernate.connection.provider", ConnectionProviderLocator},

              {"hibernate.connection.connection_string",

                "Data Source=:memory:;Version=3;New=True;"}

            };



        var source = new InPlaceConfigurationSource();

        source.Add(typeof (ActiveRecordBase), properties);



        return source;

      }

    }



    private static string ConnectionProviderLocator

    {

      get { return String.Format("{0}, {1}", TypeOfEnclosingClass.FullName,

                                    EnclosingAssemblyName.Split(',')[0]); }

    }



    private static Type TypeOfEnclosingClass

    {

      get { return MethodBase.GetCurrentMethod().DeclaringType; }

    }



    private static string EnclosingAssemblyName

    {

      get { return Assembly.GetAssembly(TypeOfEnclosingClass).FullName; }

    }



    public override IDbConnection GetConnection()

    {

      if (_connection == null)

        _connection = base.GetConnection();



      return _connection;

    }



    public override void CloseConnection(IDbConnection conn) {}



    /// <summary>

    /// Destroys the connection that is kept open in order to keep the

    /// in-memory database alive. Destroying the connection will destroy

    /// all of the data stored in the mock database. Call this method when

    /// the test is complete.

    /// </summary>

    public static void ExplicitlyDestroyConnection()

    {

      if (_connection != null)

      {

        _connection.Close();

        _connection = null;

      }

    }



    /// <summary>

    /// Initializes ActiveRecord and the Database that ActiveRecord uses to

    /// store the data. Call this method before the test executes.

    /// </summary>

    /// <param name="useDynamicConfiguration">

    /// Use reflection to build configuration, rather than the Configuration

    /// file.

    /// </param>

    /// <param name="types">

    /// A list of ActiveRecord types that will be created in the database

    /// </param>

    public static void InitializeActiveRecord(bool useDynamicConfiguration,

                                              params Type[] types)

    {

      ActiveRecordStarter.ResetInitializationFlag();

      IConfigurationSource configurationSource = useDynamicConfiguration

                                       ? MockConfiguration

                                       : ActiveRecordSectionHandler.Instance;

      ActiveRecordStarter.Initialize(configurationSource, types);

      ActiveRecordStarter.CreateSchema();

    }



    /// <summary>

    /// Initializes ActiveRecord and the Database that ActiveRecord uses to

    /// store the data based. Configuration is dynamically generated using

    /// reflection. Call this method before the test executes.

    /// </summary>

    /// <param name="types">

    /// A list of ActiveRecord types that will be created in the database

    /// </param>

    [Obsolete("Use InitializeActiveRecord(bool, params Type[])")]

    public static void InitializeActiveRecord(params Type[] types)

    {

      InitializeActiveRecord(true, types);

    }

  }

}

In my class I have overloaded the method InitializeActiveRecord to include the boolean parameter useDynamicConfiguration, governing if the configuration is dynamically built using Reflection or if the configuration in your app.config is used instead. If the parameter is not specified, it default to false (Use app.config).

Why? Brian's original code, as is, is meant to be dropped in as a new class within your test assembly, and uses reflection to dynamically determine the provider information, including the fully-qualified class name and assembly of the new DriverConnectionProvider. Reflection makes for little effort for me when I want to drop in the class into a new test assembly. Drop it in and go; no need to even modify the app.config. However, if I want to switch my provider back to SQL Server or some other platform, I have to modify the code and recompile.

My modifications remove the restriction of configuration in compiled code, allow configuration to be placed in app.config, while preserving the existing functionality for backward compatibility. By allowing app.config-based configuration, users can quickly switch back-and-forth between SQLite and SQL Server databases without having to modify and recompile the application. To use this customized ActiveRecordMockConnectionProvider class without dynamic configuration, add the following code to the configuration block of your test's app.config.

<activerecord>

  <config>

    <add key="hibernate.connection.driver_class"

      value="NHibernate.Driver.SQLite20Driver" />

    <add key="hibernate.dialect" value="NHibernate.Dialect.SQLiteDialect" />

    <add key="hibernate.connection.provider"

      value="ActiveRecordTestHelper.ActiveRecordMockConnectionProvider, ActiveRecordTestHelper" />

    <add key="hibernate.connection.connection_string"

      value="Data Source=:memory:;Version=3;New=True;" />

  </config>

</activerecord>

The catch is that you will need to know the fully-qualified class and assembly information for your provider (Line 6, above). This means you will have to modify it for every test assembly. To get around this, compile the code into a separate assembly (I called mine 'ActiveRecordTestHelper.dll'), and reference this new assembly in your test assembly. By using a separate assembly, you no longer need to modify the activerecord configuration block for every instance, and can reuse the same block everywhere the new assembly is referenced.

And to switch over from in-memory SQLite to SQL Server, just comment out the SQLite block and uncomment the SQL Server block (or whatever other provider you are using).

Download: ActiveRecordMockConnectionProvider.zip
Includes:

  • Source code for the ActiveRecordMockConnectionProvider class
  • Sample Class that uses the new provider
  • Sample app.config containing the ActiveRecord block using the provider.
  • Compiled versions of ActiveRecordTestHelper.dll

As always, this code is provided with no warranties or guarantees. Use at your own risk. Your mileage may vary.

And thanks again to Brian Genisio.

Watch the PDC Keynotes from Ann Arbor

Interested in the Ray Ozzie keynotes next week, but can't make it to PDC? Come watch the two keynotes (Monday and Tuesday) at SRT Solutions in Ann Arbor. This community event will include remote viewing of the keynotes and discussion about the news. Lunch will be provided, as our local Microsoft office is sponsoring the event for both days. (Thank you, Microsoft!)
Remote Viewing & Discussion of the Ray Ozzie Keynotes
Monday, October 27, 11:30a-2:00p - Register
Tuesday, October 28, 11:30a-2:00p - Register
SRT Solutions
206 S. Fifth Avenue, Suite 200
Ann Arbor, Michigan 48104
Come out for the show. Space is limited, so please register. (Note: if you wish to attend both days, you must register for each day separately.)
I look forward to seeing you there.
Posted by Jay Harris is Cpt. LoadTest
Filed under:

Speaking at AADND on CI, 08-Oct-08

Tomorrow night, Wednesday, 08 October, I will be speaking at the Ann Arbor Dot Net Developers meeting. We will be discussing Continuous Integration, focusing on CI as a process, not just a toolset. Come out to Ann Arbor, enjoy some pizza, and hear about what Continuous Integration can do for your development cycle.
Continuous Integration: It's more than just a toolset
Wednesday, 08 October, 2008 @ 6:00pm
SRT Solutions
206 South Fifth Ave, Suite 200
Ann Arbor, MI 48104
Session Abstract:
Does your team spend days integrating code at the end of a project? Continuous Integration can help. Using Continuous Integration will eliminate that end-of-project integration stress, and at the same time will make your development process easier. But Continuous Integration is more than just a tool like CruiseControl.Net; it is a full development process designed to bring you closer to your mainline, increase visibility of project status throughout your team, and to streamline deployments to QA or to your client. Find out what Continuous Integration is all about, and what it can do for you.

Right like a Writer with Microsoft Word Grammar Options

In Right like a Writer, I mentioned how a list of items should include a comma after every item except the last, including after and or or, and how you should only use one space after a period, rather than two. All versions of Microsoft Word can be configured to monitor for both of these using the grammar settings built in to the application; it will identify violations during regular grammar checks. Here's how to enable these options in MSWord 2007:
  1. Access Word Options
    Access Word Options by clicking the Office Button in Microsoft Word (the Office logo in the top-left corner of the window), and click on the Word Options button in the lower-right corner of the menu popup. The Word Options window should display.
  2. Access Proofing Settings
    In the Word Options window, access proofing settings by clicking Proofing on the left-side navigation.
  3. Access Grammar Settings
    Once you are in Proofing settings, you will find Grammar Settings by clicking the Settings... button next to Writing Style. Writing Style can be found under the Proofing section titled When correcting spelling and grammar in Word.
  4. Use Only One Space
    In the Grammar Settings window, the number of spaces after a period is controlled by the option titled Spaces required between sentences. This is set to don't check by default, but options for 1 space and 2 spaces are available. Set this option to 1.
  5. Include a Comma Before the Last Item
    Also in the Grammar Settings window, check for commas after and and or through the field titled Comma required before last list item. This is also set to don't check by default, though always and never are available options. Set this option to always.
Additionally, the style checks available through Word's Grammar Settings can also be very helpful. I prefer the "Grammar and Style" writing style option, as it enables all of the style checks. I encourage you to investigate all of these options, as well as enable the comma and sentence options, as they will help you write right like a writer.
Posted by Jay Harris is Cpt. LoadTest
Filed under:

Right like a Writer

At the devLink Technical Conference, one of the Open Spaces focused on Computer Science curriculum at universities, and what things that the developer community would CRUD on the CompSci tradition. Though I did not have opportunity to participate in the discussion—I was facilitating an Open Space on Continuous Integration, next door—I do have one proposal: "Writing." For Computer Scientists—a traditionally introverted and communication-challenged group—programming in English (substitute with your native language) should be paramount. Communicating to humans is part of our job description, and we must be able to do so effectively and using their language, whether it be for status updates, business justifications, SOWs, proposals, or just another email. Developers need to communicate effectively; write well rather than write good. We must be right like a writer.

We programmers should write like we code. The written word should be concise, to the point, just like code. Coders do not frivolously use fancy namespaces and complicated classes so that their code looks smart, as it has the opposite effect by resulting in bloated, inefficient, unmaintainable systems. Big words implemented frivolously for the sake of sounding smart perform the opposite function, and likewise result in bloated, inefficient, unmaintanable text. We avoid power robbers in our code, such as using string builders rather than underperforming string concatenations, and should avoid similar performance kills in our writing. Additionally, using the wrong keyword in code, or misusing grammatical marks in our code, results in compiler errors or runtime errors. The written word—a language void of any compiler benefits—throws runtime exceptions on execution when it is improperly authored, much like JavaScript or XSL.
“Vigorous writing is concise. A sentence should contain no unnecessary words, a paragraph no unnecessary sentences, for the same reason that a drawing should have no unnecessary lines and a machine no unnecessary parts. This requires not that the writer make all sentences short or avoid all detail and treat subjects only in outline, but that every word tell.” — William Strunk
But like a programming language, English is simply a matter of keywords and laws. We must learn the rules of the system; we must learn its syntax; we must learn how to test and validate our code before shipping it off to a client or to production. Approaching the English language like we approach a programming language would also provide an effective learning mechanism for us developer-types. This would make an effective course at university: "Writing : For Programmers." Learn English like we learn any other language—approach it using our virtues—as what works for us may not be the same path that works for an English major.

Throughout my career, I have noticed a few areas that are typically mis-coded. I have included a few items below that every developer should be aware of to help learn English's keywords, its laws, and to provide opportunities to improve end-user experience.

Knowing the Language at an Elementary Level
  1. Homonyms : words that sound the same but can mean different things. This is often a challenge for people new to English, but even veterans get confused. Everyone should learn the difference, and make proper use a habit. And proof read, as spell check will not catch misuse of homonyms. This applies to:
  • Their / There / They're
  • To / Too / Two
  • Your / You're
  • Its / It's
  • Hear / Here
  • Threw / Through
  • Write / Right
  • Irregardless is not a word.
  • Who vs. Whom : Who, the subject, is doing the acting, and whom, the object, is being acted upon. The shortcut is to use who and whom as you would he and him. (Remember that him and whom both end in "m".) <Who did what to whom for how many jellybeans? He did that to him for five jellybeans.>
  • Me vs. I : Follow the same rules as for who vs. whom, above. The subject is doing the acting, and the object is being acted upon. Subject pronouns are I, he, she, we, they, and who. Object pronouns are me, him, her, us, them, and whom. <Sally gave me five dollars. I used to money to buy lunch.>
  • Than vs. Then : A comparison (than) vs. a measure of time (then). In code, than is used when describing a comparison operator; the '>' operator is a greater-than operator. In code, time sequences are an if...then statement. <Apples are better than oranges. I will eat my apple first, then I will eat my orange.>
  • Knowing the Language at a High School Level
    1. Power Robbers : Never use due to the fact that. It weakens your sentence. Use because.
    2. Contractions : In formal writing (e.g. Proposals, SOWs), avoid contractions. Contractions are for casual writing. Think along the lines of a Debug Build versus a Release Build.
    3. Simply & Obviously : Avoid using simply and obviously as it may be both to you, but neither to your audience. If it was simple or obvious, then you didn't need to write it.
    4. Use one space after a sentence, not two. A PC is not a typewriter. On a typewriter, with fixed-width fonts, two spaces are preferred, but on a PC, True Type fonts will properly space "<dot><space>" for you. Don't believe me? Open up any book and look at the spaces between sentences. Microsoft Word has an option to indicate this for you under grammar preferences.
    5. Effect vs. Affect : Effect is the result, affect is the action. Noun and verb. <Poor engine performance is the effect of ignored maintenance. Ignoring maintenance affects engine performance.>
    Knowing the Language at a Collegiate Level
    1. Lists : Just like when defining an array, use a comma after every item in a list except the last. This includes before "and." <I like red, white, and blue.>
    2. i.e. vs. e.g. : The first is in other words and the second is for example, though this does not do much for clarity. Essentially, i.e. is a complete, clarifying list, while e.g. is an incomplete list of examples. <I watch the three stooges (i.e., Larry, Curly, and Moe). I like all four-player card games (e.g., Euchre, Spades, and Hearts).>
    3. Semicolons : Semicolons are used to separate two independent yet related clauses that could be broken into separate sentences. <The water is very hot; I hope I don't burn myself.> Also, use semicolons to separate items in a list where the items contain commas. <When the cards were dealt, Jack had a straight; Sally had two nines, two fives, and a queen; and George had a full house.>
    Be mindful of your native language. It is the one you use the most, even more than C#, or Ruby, or Java. If you don't already own a copy, pick up The Elements of Style by Strunk & White; if you do own a copy, either have it at your desk so you can use it, or give it to someone who will. Effectively communicating with humans, using their rules, will help you have better testing, better design, better requirements, and have a better job. Become an effective English developer, and it will help you be a more effective developer, overall.

    Speaking at GLUGnet Flint on CI, 11-Sep-08

    Tomorrow night, Thursday, 11 September, I will be speaking at the GLUGnet Flint meeting. We will be discussing Continuous Integration, focusing on CI as a process, not just a toolset. Come out to Flint, enjoy some pizza, and hear about what Continuous Integration can do for your development cycle.
    Continuous Integration: It's more than just a toolset
    Thursday, 11 September, 2008 @ 6:00pm
    New Horizons
    4488 West Bristol Road
    Flint, MI 48507
    Session Abstract:
    Does your team spend days integrating code at the end of a project? Continuous Integration can help. Using Continuous Integration will eliminate that end-of-project integration stress, and at the same time will make your development process easier. But Continuous Integration is more than just a tool like CruiseControl.Net; it is a full development process designed to bring you closer to your mainline, increase visibility of project status throughout your team, and to streamline deployments to QA or to your client. Find out what Continuous Integration is all about, and what it can do for you.

    conferencesStream.Flush(); //Give Camp, CodeStock, devLink Wrap-up

    My summer has been what seems like a steady stream of major events in the development community. It really all began with my election to the board of GLUGnet last April, which immediately put me as a planner for the first Lansing Day of .Net, for which I handled the web site and branding. The event, which I blogged about previously, was held on June 21, 2008, and was a huge success. We will definitely have the conference again next year, and are already brainstorming ways to make the event even better.

    Three weeks after LDODN, on July 11-13, was Ann Arbor Give Camp. Give Camp was an event for charity, where area developers volunteered their weekend to code for charity. The Heartland District truly displayed their selflessness and passion with their willingness to endure three days of Ninjas-On-Fire coding, often sacrificing sleep to accomplish deadlines, to help out not-for-profits that likely would never have the budget for a high-quality, professionally developed web site. I was also impressed by the event sponsors for their donations and contributions; Washtenaw Community College provided the venue for no cost, Verio provided free hosting for each charity's site until 2010, and Microsoft provided to each of the charities free copies of all of the software needed to support and maintain the new applications. The planning staff should be commended for this event, too; they went to no end to enable the development teams, and to meet our every desire. There was plenty of food, plenty of snacks, plenty of fluids, and plenty of games for when we needed to occasionally decompress. We requested ice cream; we got ice cream. Someone on my team even requested a Cherry Coke, and one of the organizers made a midnight run to the local gas station to pick up a bottle. The event was great, and we had a blast. I will be there next year, maybe even running a team of my own.

    Another four weeks brought CodeStock, August 9, in Knoxville, TN. Dave Redding, The Wife, and I hopped in Dave's Charger and cruised the nine hours from Brighton, MI to Knoxville on Friday night, arriving at about 3:30am for the 7:30am registration. Michael Neel and crew put on a great show. I finally got to see the Joe O'Brian / Amanda Laucher presentation on DSLs and Brian H. Prince's 'Soft Skillz ' talk. (I highly recommend both.) But what really made the event were the Open Spaces, organized by Alan Stevens. We had some enlightening discussions, such as improving User Group participation, and developing in .Net on a Mac. The after party at Alan's house included a time for socializing outside of a technical setting, and included a friendly game of Texas Hold'em. Dennis Burton was the big winner, and graciously donated his winnings to the Hands On Museum in Ann Arbor, the charity that Michael Eaton worked on during Give Camp.

    In the shortest gap of the summer, I only had to wait two more weeks for devLink, August 22-23, in Murfreesboro, TN. However, there was no 9 hour drive, as The Wife and I hitched a ride on the devLink Bus. Organized by Amanda Laucher (and others)--my employer, Latitude Consulting Group, was also one of the sponsors--we chartered a coach for the weekend to take some of the local developers down to devLink. The bus started in Grand Rapids, and made pick-up stops in Lansing, Detroit, Toledo, Columbus, and Cincinnati. We made some "detours" along the way, and the seats were a little uncomfortable for sleeping, but we all had a great time; we had some great discussion, we watched some movies, and Mike Eaton, The Wife, Eric Vogel , and I even played a few rounds of euchre. We had one minor glitch on the return trip, as one of the right rear tires blew out at about 1:30am while traveling at 65mph up I-71, but we even had fun on the 3 1/2 hour delay, as we took over a Waffle House in Carrollton, Kentucky, were entertained by "The Great Pork Chop Incident," and a few riders extended the Open Spaces discussions from the conference.

    As for devLink itself, I went to focus on the Open Spaces. Four different Open Space discussions were on hand for each of the session blocks throughout the two-day conference. I attended sessions on Developing the Developer Community; on why Comments are Evil; on How "Should" Changed My Life (a discussion on BDD , and creating effective tests); on Microsoft, Open Source, and CodePlex; and I facilitated a discussion on Continuous Integration. I only went to one session throughout the conference: Jeff Blankenburg's talk on Silverlight. I challenged him to show me a reason to use Silverlight that didn't include gradients, spinning ghost animations, or anything else that I have been able to do in Flash since version 4. After his talk, I'm actually motivated to dig in. Over the years, I have created a few Flash games--nothing too special, as they were primarily about learning a specific component, like collision detection--and I plan on starting with converting them to Silverlight. It should give me a good opportunity to grok the space.

    But to me, the best part about this summer isn't the things I have learned, or the code I've produced, but the relationships and bonds that have formed. I have made many new connections this summer, and made some great new friendships, and I look forward to many more. The list is made up of people all smarter than I am, yet I am treated as an equal. Every time we connect, I learn a lot, professionally and personally. I have grown a lot over this past year, and I owe every bit of it to them (and to the kick in the pants from Dennis Burton that pushed me to get involved in the first place).

    Here's to what's next.

    Posted by Jay Harris is Cpt. LoadTest
    Filed under:

    Do You Twitter?

    A question was posed on LinkedIn asking readers if they used Twitter, and if so, how and why? Because of the impact that Twitter has had on my life, I felt compelled to answer.

    Twitter is a phenomenal tool that I feel should be included in any developer's toolset. I use Twitter for both business and personal reasons, including socializing with friends, scheduling lunch, and also for networking with business associates. There is a lot of value in having a consolidated service through which I can plan both happy hour and a business meeting. I have also made many new business contacts through the service, and the personal nature of Twitter communications have created relationships that are much more solid than those from other services, such as LinkedIn. When I travel to a conference such as devLink or Codestock, I often meet these twitter contacts for the first time, yet the bond that has matured on Twitter makes it seem like we have been friends for a long time.

    In addition to networking, Twitter is effective with asking questions and getting quick responses (similar to what was on LinkedIn), or for driving traffic to my blog by promoting when there is a new post.

    I access Twitter four different ways: through Witty on my primary computer, directly through the web when not at my primary computer, through Twitterific on my iPod Touch, or through SMS on my phone. The possibilities allow me to stay connected wherever I go. I have a presence on many of the social networks, too, such a Pownce, Jaiku, and Identi.ca, but I rely on Twitter. I can't live without it.

    Do you Twitter? How do you use Twitter? How has it had an impact on you?

    Posted by Jay Harris is Cpt. LoadTest
    Filed under: ,

    Today is Contribupendence Day!

    Jeff Blankenburg came up with a good idea! As I go through my LinkedIn connections, I see that not many of them have recommendations. And it's not that these people don't deserve them--many of these connections I consider to be amongst the brightest people in the industry. As a community, and in many cases simple as a people, we don't often take the time to help each other out. We may pat each other on the back for recognition of talent, but we don't often do so in a public forum. Social Networking sites like linked in are phenomenal for things like job hunting, not necessarily for the networking but because potential employers will peruse these sites to gather information about a candidate, and these recommendations can go a long way towards impressing the employer.

    Enter Contribupendence Day! Jeff came up with the idea for one grand call-to-action where the entire community gets together to "tell the world about the people we work with." Everyone should comment / recommend / praise their friends, colleagues, associates on sites such as LinkedIn or Plaxo. No strings attached. No expectation that they will return the favor. Just do a good deed for your buddy, because that's what we should all be doing anyway, everyday.

    I have a few folks that I have been meaning to recommend, and I just haven't gotten around to it. This is good motivation, and a great idea. You should, too.

    Today we celebrate our Contribupendence Day.

    Posted by Jay Harris is Cpt. LoadTest
    Filed under: