17 Aug 2010

Who Loves Their Developers More

8 Comments Uncategorized

Last night as I was talking with Danny Diaz about the importants of good programming language documentation.  It occurred to me that the level of effort a company puts into its documentation is a direct reflection on how it sees the developer in relation to its products.  If there is a lot of thought, love, and detail put into the documentation the company most likely cares very much about the developers experience from cradle to grave.  If the documentation is haphazardly put together and no common UIX efforts were made then the company most likely cares very little about new developers, and only begrudgingly puts documentation online for its seasoned developers because it is the industry norm and is expected of them.

As a test I decided to look at the documentation posted online for five of the most common languages found out there today, that are tied to a specific company. 

  • C# – Microsoft
  • Java – Oracle
  • Objective-C – Apple
  • Ruby (Ruby On Rails) – 37signals (I know this is a framework, but this seems like the company with the most influence)
  • PHP – The PHP Group

I needed to compare documentation on a somewhat equal footing, something that was going to be common across all the languages, so I settled on looking at the documentation for strings.  As I was doing this I found some very interesting dichotomies between the layouts and presentation used by each of the companies, some just didn’t care, others cared a great deal.  But the biggest factor was the usability of the documentation, some it looked like they simple wanted to present the information on the screen so they could say they have documentation, others cared very much about the UX, some look like they cared by like anything else a bad design seems to be weighing down their efforts.

Here are the five criteria I used to judge each set of documentations on a 0 to 5 scale.

  1. Quality of documentation
    Does the documentation contain just the bare-essentials or does it contain helpful security, performance, and warning considerations that the developers should know about so they don’t run into too many gotcha’s too far down the line.
  2. Ease of navigation
    This is important because if you cannot navigate the documentation easily and drill into exactly what you need to look up, it severely hoppers you productivity as a developer.
  3. Code use examples
    Sometimes even if you have the API, the use of it isn’t exactly understood from the documentation alone, so examples of how the method should be used are always a welcomed addition for determining if you are on the right track or not.
  4. Easy to read URL
    Having an easy to read URL is important, because not only does it help with things like SEO, since Google is always the first place I go when searching for documentation, it also helps in quick navigation of the documentation if you know exactly the class you are looking for.
  5. Ease of switching between documentation versions
    Sometimes you queries in Google don’t exactly bring you to the right version of the documentation that you need, but if the site makes it easy to switch between versions then the right documentation is only a click away. Or on the other side of that coin, you cannot be using the latest and greatest in your job, but you still need to find relevant information to the version you are working with.

So lets get started.

PHP

php

The PHP documentation for strings was very poor, but I think that is because strings are considered to be a primitive in the PHP world, so all they could do was document other methods that interact with strings.  However, their over all documentation was poor and would have only received one out of five if it wasn’t for the excellent user contributed content and examples that each page has.  I don’t know if the excellent user contributed content was born out of necessity of bad documentation, part of the culture, or a combination of both but it seems to get the job done for the most part.  Besides the content the navigation was horrid, there is not an easy way besides search to find other relating documentation, besides drilling back up the navigation tree, and as far as I could see there wasn’t an easy way to switch to the different versions of PHP if you weren’t using the latest and greatest version.  And they seem to maintain this mid-90’s book paging documentation practice that allows you to continue to the next section of the documentation as if it was divided in to chapters, which really only reinforces the point that they haven’t looked at their UX for probably at least 10 years.  So that all contributed to the following scores:

  • Documentation Quality (2/5)
  • Navigation (1/5)
  • Code Examples (3/5)
  • Easy Url (4/5)
  • Version Switching (0/5)
  • Overall (2/5)

Ruby

ruby

Note: The documentation provided on Ruby On Rails seems to be a direct copy from Ruby Doc.

The documentation quality was very good, but on the same token very minimal it only gave you very terse information about each method, but the saving grace was definitely the code examples as far as the actual documentation went.  The navigation is very good for in-document jumping around, however it is very poor for browsing other classes in the Ruby language, on the other hand the URL’s seems to be cleanly represented and a power-user would be able to jump between documentation with easy by just using the URL.  Version switching was non-existent.  Which all resulted in the following scores.

  • Documentation Quality (3/5)
  • Navigation (3/5)
  • Code Examples (4/5)
  • Easy Url (4/5)
  • Version Switching (0/5)
  • Overall (3/5)
  • Java

    java

    The documentation quality was very good, however after you get past the header of the document each method is only tersely documented and there were very few code examples or warning to base your decisions on. The UX as you might be able to tell hasn’t been updated probably since Java was released in 1995, their idea of navigation seems to be based on browser frames and one off targeted screens that just show a list of classes for instance in the namespace.  On the other hand the layout was simple, and a power-user could easily jump around the documentation with a few targeted clicks to find out more about the properties vs methods vs constructor.  The URL is very easy for a power-user to navigate through, because the classes and namespaces are right in the URL including the version, so it is everything you need to get right to the documentation you are looking for.  You can easily navigate to other version of the documentation by just changing the version in the URL, which isn’t ideal, but it is better than no method at all.  The only caveat is that the Java versioning isn’t consistent, but they seem to have redirects in place for common mistakes.  This all resulted in the following scores for the documentation:

  • Documentation Quality (3/5)
  • Navigation (3/5)
  • Code Examples (2/5)
  • Easy Url (4/5)
  • Version Switching (2/5)
  • Overall (3/5)
  • Objective-C

    obj-c

    The documentation quality is very good, and if I had to guess Apple took the structure of the Java documentation and just added the typical Apple flare to it.  Because most of the elements are laid out in the exact same order as the Java documentation right down to the navigation.  But a plus for Apple is that they got rid of the 90ish navigation techniques and added something a little more modern, but still not that great.  Instead of navigating the document by clicking links you select a drop down which will take you to the part of the documentation you are looking for.  In addition to that they have a nice menu on the right hand side that lets you jump around the class, but nothing more, so you can’t use it to browse the entire library.  One weird thing I encountered which I am still scratching my head at for the reasoning is the next button at the top of the page. It seems to take you just to the deprecated methods and then if you click it again takes you to the document update history, seems totally useless to me.  In addition there was no way to switch between versions and the URL structure was the most horrid I have seen, so that all resulted in the following scores:

  • Documentation Quality (3/5)
  • Navigation (3/5)
  • Code Examples (1/5)
  • Easy Url (1/5)
  • Version Switching (0/5)
  • Overall (3.5/5)
  • C#

    csharp

    Lightweight

    csharp2

    Classic

    csharp3

    ScriptFree

    I have to say that Microsoft is basically the cream of the crop as far as documentation goes.  They have 3 different views of the documentation depending on your needs and habits for browsing.  All 3 of the themes had a very clear UX that really shows that they care about how the developer perceives the documentation.  Because of the three themes the navigation varied slightly between them but all of them were very consistent in layout and approach, which made transitioning easy.  The URL is one of the easiest I have seen, because the structure is /{language}/library/{namespace}.aspx, which is very clear, easy to navigate, and short enough were you can easily tell where you are going before you click a link.  The code examples were top notch and most methods and properties had full code examples that you could copy and past and run right in Visual Studio.  In addition, they allowed community posting on the documentation like we found with PHP.  And Microsoft was the only company that offered switching of versions right in the documentation, even though it was only the Classic theme it was a very nice addition.  For the other themes you can switch versions with the URL.  Other welcome additions was the namespace navigation in the Classic theme and ability to drill out of the namespaces with the other themes and see all the peer classes in each namespace.  Overall I am very impressed by MSDN, which shows in the scores below:

  • Documentation Quality (5/5)
  • Navigation (4/5)
  • Code Examples (5/5)
  • Easy Url (5/5)
  • Version Switching (4/5)
  • Overall (4.5/5)
  • Conclusion

    As most of you know that have read my blog for any amount of time, I am a fan of C# as a programming language, and I always knew that MSDN had the best developer documentation.  But it wasn’t until going through this exercise that I realized how far ahead Microsoft is in having one of the best developer experiences around.

    I am interested in hearing what you like and hate about each of these documentation sites, and any others you think warrant a mention.

    16 May 2010

    TimeUUID only makes sense with version 1 UUIDs

    2 Comments FluentCassandra

    In a world where we are all use to dealing with objects we often forget that everything gets reduced to ones and zeros before being transmitted over the wire to the destination.  Most times the destination easily handles converting this object back in to an object on the other side that is easily understood and consumed.  The frustration comes when we run in to a situation where the other side doesn’t understand our transmitted data.  This can often cause us to pull our hair out, become irritable, and throw out hands up in disgust.  Well recently I have been doing all that when trying to solve what sounds like simple problem on the surface.  Sending the bytes of a Type 1 UUID, or GUID, over the wire from .NET to a server running on Java.

    The Problem

    It is a simple one, I need to transmit a Guid from .NET over to a UUID in Java.  Mind you Guid and UUID solve the same thing in the differently languages so this isn’t a case of mis-mapped different objects.

    TimeUUID only makes sense with version 1 UUIDs

    This error is the error that came up each and every time I sent the GUID object over to the Java Server using the following method.

    Guid g = new Guid("38400000-8cf0-11bd-b23e-10b96e4ef00d");
    var bytes = g.ToByteArray();
    
    Server.Transmit(bytes); // this method call is an example

    The part of this that really made me pull my hair out was the fact that the GUID that I was sending over was a valid Type 1 UUID.  If you don’t believe me check it out here.  So after writing a bunch of unit tests and double and triple checking the fact that the GUID I was sending over was a Type 1 GUID, it finally dawned on me that maybe the problem was the fact that Java handled the byte order of the UUID different than .NET.

    So I wrote a quick Java program to verify this thesis.  And this is what I found.

    UUID x = UUID.fromString("38400000-8cf0-11bd-b23e-10b96e4ef00d");
    System.out.println(x.toString());
    System.out.println(x.version());
    
    // results:
    // 38400000-8cf0-11bd-b23e-10b96e4ef00d
    // 1
    
    byte[] byteArray = { ... the bytes here ... };
    ByteBuffer bb = ByteBuffer.warp(byteArray);
    UUID y = new UUID (bb.getLong(), bb.getLong());
    System.out.println(y.toString());
    System.out.println(y.version());
    
    // results:
    // 00003840-f08c-bd11-b23e-10b96e4ef00d
    // 11

    You might have noticed that the byte order for the first 8 bytes of the UUID have been reversed for each section.  So I reversed the bytes in my byteArray and here is the output I received.

    // results:
    // 38400000-8cf0-11bd-b23e-10b96e4ef00d
    // 1

    I jumped for joy when I saw this come out correctly, because it meant that I had solved the problem.

    But Not So Fast

    I still needed to write the code on the .NET side to handle reversing and unreversing these bytes when sending over to and receiving from the Cassandra server.  So to correct this I just created a simple byte array converter for my Cassandra type TypeConverter object for TimeUUID. 

    private byte[] ReverseLowFieldTimestamp(byte[] guid)
    {
        return guid.Skip(0).Take(4).Reverse().ToArray();
    }
    
    private byte[] ReverseMiddleFieldTimestamp(byte[] guid)
    {
        return guid.Skip(4).Take(2).Reverse().ToArray();
    }
    
    private byte[] ReverseHighFieldTimestamp(byte[] guid)
    {
        return guid.Skip(6).Take(2).Reverse().ToArray();
    }
    
    public override object ConvertTo(ITypeDescriptorContext context, System.Globalization.CultureInfo culture, object value, Type destinationType)
    {
        if (!(value is Guid))
            return null;
    
        if (destinationType == typeof(byte[]))
        {
            var oldArray = ((Guid)value).ToByteArray();
            var newArray = new byte[16];
            Array.Copy(ReverseLowFieldTimestamp(oldArray), 0, newArray, 0, 4);
            Array.Copy(ReverseMiddleFieldTimestamp(oldArray), 0, newArray, 4, 2);
            Array.Copy(ReverseHighFieldTimestamp(oldArray), 0, newArray, 6, 2);
            Array.Copy(oldArray, 8, newArray, 8, 8);
            return newArray;
        }
    
        if (destinationType == typeof(Guid))
            return (Guid)value;
    
        return null;
    }

    And a little coding and some unit tests later, I was able to verify that the UUID (or GUID) would be correctly transmitted to Java and read back from Java correctly with the changes I made above.  I don’t completely understand why the byte order is different, because UUID is a pretty solid standard.  But I am sure it has something to do with the Endianness of the two languages.

    In The End

    This turned out to more of an adventure than I thought it would be, and I had to break out some Java code to do it, but after about an hour coding and testing, everything seems to be working and TimeUUID is now supported under .NET. 

    Note: By the way I really didn’t want to install Eclipse to test out Java snippet, luckily Mono Develop supports Java development.

    18 May 2008

    How to create a YUI Compressor MSBuild Task

    18 Comments Uncategorized

    Recently for IdeaPipe I have been looking for ways to deliver my content more quickly and reduce unnecessary bandwidth use.

    According to Yahoo’s Performance Team more than half of the viewers of the Yahoo websites start with an empty cache, which means the browser has to download all the resources for the first time. This combined with a high traffic website and unneeded white space and comments can really add up to a significant bandwidth use. There are many popular ways to minify your static content tax on your bandwidth, using many popular tools, as described in this excerpt from Yahoo:

    In terms of code minification, the most widely used tools to minify JavaScript code are Douglas Crockford’s JSMIN, the Dojo compressor and Dean Edwards’ Packer. Each of these tools, however, has drawbacks. JSMIN, for example, does not yield optimal savings (due to its simple algorithm, it must leave many line feed characters in the code in order not to introduce any new bugs).

    The goal of JavaScript and CSS minification is always to preserve the operational qualities of the code while reducing its overall byte footprint (both in raw terms and after gzipping, as most JavaScript and CSS served from production web servers is gzipped as part of the HTTP protocol).

    The cream of the crop seems to be a tool Yahoo developed to deliver its own static text content scripts and styles, the YUI Compressor:

    The YUI Compressor is JavaScript minifier designed to be 100% safe and yield a higher compression ratio than most other tools. Tests on the YUI Library have shown savings of over 20% compared to JSMin (becoming 10% after HTTP compression). Starting with version 2.0, the YUI Compressor is also able to compress CSS files by using a port of Isaac Schlueter‘s regular-expression-based CSS minifier.

    The YUI Compressor is a Java JAR file that can be download from Julien Lecomte Blog.

    The YUI Compressor yielded exceptional results, however it was missing one thing. Integration in to my build and deployment process. In IdeaPipe I use a MSBuild script to compile, manipulate, and prepare for publishing. So naturally I built a MSBuild Task to minimize my JavaScript and CSS files.

    The magic actually happens by invoking Java in an external process for each file passed in to the task.

    Process process = new Process();
    process.StartInfo = new ProcessStartInfo {
    	FileName = @"c:\program files\java\jdk1.6.0_06\bin\java.exe",
    	Arguments = String.Format(
    		@"-jar ""C:\development\tools\yuicompressor-2.3.5.jar"" --type {0} --charset utf8 {1} -o ""{2}"" ""{3}""",
    		type,
    		ShowWarnings ? "--verbose" : String.Empty,
    		newFile,
    		oldFile
    		),
    	UseShellExecute = false,
    	CreateNoWindow = true,
    	RedirectStandardOutput = true,
    	RedirectStandardError = true
    };
    process.Start();
    process.WaitForExit(5000);

    Then I read the warning from the standard error output and send them back to Visual Studio as a compile warning if the ShowWarning property is true.

    string[] warnings = process.StandardError.ReadToEnd()
    	.Replace("\r", String.Empty)
    	.Split(new string[] { "\n\n" }, StringSplitOptions.RemoveEmptyEntries);
    
    foreach(string warning in warnings)
    	Log.LogWarning(null, null, null, oldFile, 1, 1, 1, 1, FormatWarning(warning), null);

    To integrate this in to my MSBuild script I had to first register my task:

    <UsingTask TaskName="ManagedFusion.Build.YuiCompress" AssemblyFile="$(ProjectDir)..\ManagedFusion.Build\bin\$(ConfigurationName)\ManagedFusion.Build.dll"/>

    Then setup my ItemGroup for the files:

    <ItemGroup>
    	<JavaScriptContent Include="$(SourceWebPhysicalPath)\**\*.js" />
    	<CssContent Include="$(SourceWebPhysicalPath)\**\*.css" />
    </ItemGroup>

    Then finally I setup my task to perform the minimization against the JavaScript and CSS files seperately:

    <Target Name="AfterBuild">
    	<!-- do other stuff to prepare for publishing -->
    	<YuiCompress Files="@(JavaScriptContent)" Type="JS" />
    	<YuiCompress Files="@(CssContent)" Type="CSS" />
    </Target>

    You can easily incorporate this in to your own MSBuild scripts or even your Visual Studio Project which is just an MSBuild file for compiling your source code for the project. I have included my source code below:

    Download: YUI Compressor MSBuild Task Source

    Note: There are a couple of static paths to be on the look out for and modify as necessary for your own code. In my code the Java runtime is loaded at c:\program files\java\jdk1.6.0_06\bin\java.exe and the YUI JAR is located at C:\development\tools\yuicompressor-2.3.5.jar.

    Update (2008-5-21): Thanks George, apparently IIS doesn’t like serving straight C# files. So I added the code to my Coder Journal Source Control, so that it can be downloaded from there.