PITADEV
Curiosity killed the developer's project.

Stifling the Oral Tradition; Documenting Self-Documenting Code

Friday, 7 August 2009 12:54 by aj

I have a hard time interviewing people.  No, it’s not because I don’t enjoy being a complete asshole or because I don’t know about the perfect interview question.  It has everything to do with the fact that I’m a fatally honest son-of-a-bitch.  So, when someone comes into an interview for a developer position at my company and asks what methodology we use, I always answer, “We don’t.”  It’s not that we’re completely disorganized (although sometimes we’re close), it’s that we are extremely production-oriented, and since we’re not a software company, our executives could care less about Kanbans, Scrums, and Waterfalls.  I’m not excusing this.  I think it’s a crime that we aren’t following something.  But it’s the reality of the situation and it’s going to take a long time to change.

One of the biggest problems any haphazard development department like mine encounters is a total lack of documentation.  It’s a cliché that developers hate documentation.  Especially project documentation.  I’m not even sure developers should be responsible for project documentation.  However, following these simple steps, I have found that I almost enjoy documenting my large libraries and frameworks, making life easier on my peers as well as satisfying auditors, PMs, and other business riff-raff.

Note: The following has a “tutorial” feel to it.  Both Sandcastle and GhostDoc are so easy to use that if you don’t want to follow these steps as guidelines for best-practices, then just go get them and start using them.

  1. If you’re not already, get familiar with Visual Studio’s built-in XML documentation capabilities.  In C#, type “///” (‘’’ in VB) above a class, method, property, namespace, whatever.  You’ll see a nice set of comments fill in for you:
    			/// <summary>
    	
    			/// A method that does stuff.
    	
    			/// </summary>
    	
    			/// <param name="stuff">A <see cref="IDictionary{TKey,TValue}" /> that has stuff in it.</param>
    	
    			private static void DoStuff(IDictionary<string, int> stuff)
    	
    This is a well-known feature of VS, so I’m not going to spend a great deal of time on it.
  2. Use very descriptive names for everything!  I could give a crap if you name a property “ContainerForAccountInformationThatHasAReallyLongName.”  At least I have some idea what the property is.
  3. Download and install SubMain’s GhostDoc.  Let it integrate with Visual Studio as it installs.  Don’t be afraid, it’s probably smarter than you are, and it’s free.  Once you have it installed, open up your favorite project and find a class or member with a really nice signature.  Something with a lot of parameters, generic type parameters, etc., and make sure everything is following item 2.  Put your DocumentThis cursor on the member signature, right-click (or use the built-in hotkey) and select “Document This.”

    GhostDoc extends the built-in XML documentation and interprets not only your member and parameter names, but what the description text should possibly be.  And if you are naming things well, it’s usually pretty damn close to right.  It is quite configurable and even attempts to interpret situations where you should add remarks along with summary documentation.  Using GhostDoc has greatly decreased the amount of typing I do for inline XML documentation.  Here’s an example of a method documented by GhostDoc with no changes made:
    		/// <summary>
    	
    		/// Locks the process item.
    	
    		/// </summary>
    	
    		/// <typeparam name="TProcessItem">The type of the process item.</typeparam>
    	
    		/// <param name="processItem">The process item.</param>
    	
    		/// <returns></returns>
    	
    		protected override TProcessItem LockProcessItem<TProcessItem>(TProcessItem processItem)
    	
    Notice it doesn’t fill in the value for “returns,” but if you think about it, there’s really no way for it to know that.  Besides, this is the sort of typing that we should do, because it eventually provides a synopsis of what the method does.
  4. Document your code and build your project.
  5. Download and install Sandcastle.  Fire it up.  The default empty environment will set you up with a new project.SCAddSource  After saving/naming the project, in Sandcastle’s Project Explorer, right-click  “Documentation Sources” and browse to the build .exe or .dll for your project.  Alternatively, you can use the .Net solution or project file.



  6. In the Project Properties, find “HelpFileFormat.”  This is how you can configure what sort of help files you want Sandcastle to build.  There are currently three options:

    HtmlHelp1x – Standard CHM help file that we’ve all come to know and love, built with HHC.exe, which you should already have installed.
    HtmlHelp2x – HxS help file.  Note that you need to have HXCOMP.exe, which is part of the Visual Studio SDK.
    Website – A rather robust HTML website that looks a bit like an older version of MSDN.  I haven’t experimented with this, but the Sandcastle site has a lot of tips on how to use third-party plug-ins for Ajax and other cool stuff.

  7. Configure all of the other Project Properties in Sandcastle as you see fit.  You’re going to miss some stuff.  Don’t worry, Sandcastle makes it easy to see what you’ve missed.  Leave the log-related properties as their defaults.
  8. Under the “Documentation” menu, select “Build Project.”  After a short time, your build will complete.  Navigate to your “OutputPath” folder and look at your awesome new help documentation!  Then, package it up with your project so that everyone can use it, send it to your boss, and go get some ice cream.

 

While browsing through your documentation and feeling really good about yourself, you may notice some points where Sandcastle will have marked in bold-red font, [Missing <something> documentation for “a particular thing”.]  You can easily repair this by going back to your project and adding the missing XML documentation, or, if it’s a namespace, you can add namespace documentation to the Sandcastle project by using the Namespace Summaries editor found in the Project Properties for “NamespaceSummaries.”  Also, if you would rather not dig through every single page generated by Sandcastle, you can easily find missing documentation by looking at the build log, which can be accessed through “Window—>Build Log Content.”  Sandcastle highlights any warnings for missing documentation in the build log, making it very easy to scroll through and see what you might have missed.

BuildLogWarn

 

So, with a little extra work (as opposed to a ton of extra work), you can feel a bit better about your documentation habits.  I’ve found that using these simple steps has made me a better programmer as well as a better teammate.  Looking at the output from Sandcastle and adding meaningful information to my code with GhostDoc makes me pay more attention to its structure and design.  That, in itself, makes it worth the effort.

Currently rated 4.5 by 2 people

  • Currently 4.5/5 Stars.
  • 1
  • 2
  • 3
  • 4
  • 5

ReSharper C# FTW (again), VB not so much

Wednesday, 3 June 2009 13:24 by aj

resharper I write both VB and C#.  Anyone who’s read this blog knows that I prefer C#, but VB is my company’s standard, so anything I write that will be deployed is written in VB.  To keep my skills from decaying and in something of a silent protest, I do all of my prototyping and test code in C#.  I have ReSharper 4.5 Full Edition installed, and although JetBrains states that 4.5 has enhanced VB9 support, I’m still amazed at how much more it does for me when I switch over to a C# project.  It’s possible I don’t have it configured correctly, and I haven’t customized it at all yet (too busy coding, I guess).  Either way, here’s an example of what ReSharper does with the exact same method, first in C#, then in VB.

The method is a simple string parsing method.  I have a DB2 table full of strings.  Somewhere in each string is an eight digit number that I need.  However, this data was populated using a regular expression (^\D?\d{8}\D?$) that searched for all strings that have one non-digit wildcard before or after an eight digit string, which made room for situations where an octathorpe (#), parenthesis, colon, or anything else may have been directly in front of or following the desired string.  Since the eight-digit string is all I really care about, here’s what might be a typical (albeit poorly written to accentuate ReSharper’s capabilities) little method to chop off the leading and/or trailing wildcard, if it exists, and return the meaningful eight digit string:

   1: private String GetRealFieldData(string regexMatchData)
   2: {
   3:     if (regexMatchData.Length == 10)
   4:         return regexMatchData.Substring(1, 8);
   5:     else if (regexMatchData.Length == 9)
   6:     {
   7:         if (System.Text.RegularExpressions.Regex.IsMatch(regexMatchData, @"^\D"))
   8:             return regexMatchData.Substring(1);
   9:         else
  10:             return regexMatchData.Substring(0, 8);
  11:     }
  12:     else
  13:     {
  14:         return regexMatchData;
  15:     }
  16: }

Ugly, ain’t it?  ReSharper thought so, too.  Here’s what the snippet looks like in my IDE with ReSharper’s default options enabled:

ResharperCs1

Look at all of the possibilities that ReSharper found!

ResharperCs2First is the method signature, which (since for this blog I put this code in a console application) can be made static. That’s pretty boring by ReSharper standards, but I went ahead and let it do it anyway, since it doesn’t really hurt anything and I am generally of the mind that members should have explicit and accurate modifiers.

ResharperCs3 Let’s get to the meat, which surrounds all of the if-else conditions.  Notice that they are all grayed out, and that ReSharper put a green underline under the if’s.  Anything that gets grayed out is unnecessary code, and I love brevity, so I told ReSharper (by hitting the default ALT+Enter keyboard combination to expand the little light bulb) to go ahead and fix the bad else’s, which resulted in this snippet:

   1: private static String GetRealFieldData(string regexMatchData)
   2: {
   3:     if (regexMatchData.Length == 10)
   4:         return regexMatchData.Substring(1, 8);
   5:     if (regexMatchData.Length == 9)
   6:     {
   7:         if (System.Text.RegularExpressions.Regex.IsMatch(regexMatchData, @"^\D"))
   8:             return regexMatchData.Substring(1);
   9:         return regexMatchData.Substring(0, 8);
  10:     }
  11:     return regexMatchData;
  12: }

OK, that’s a little better.

ResharperCs4   But the real fun lies in the green underline under the embedded if statement, where Regex.IsMatch() is called.  I was curious to see what the light bulb said, and even more curious after the light bulb offered a “Replace with ‘return’” option.  So I let it rip, and was delighted to see the results, which will ultimately make me a better C# programmer since I learned a little more C# syntax.

   1: private static String GetRealFieldData(string regexMatchData)
   2: {
   3:     if (regexMatchData.Length == 10)
   4:         return regexMatchData.Substring(1, 8);
   5:     if (regexMatchData.Length == 9)
   6:     {
   7:         return System.Text.RegularExpressions.Regex.IsMatch(regexMatchData, @"^\D") 
   8:             ? regexMatchData.Substring(1) 
   9:             : regexMatchData.Substring(0, 8);
  10:     }
  11:     return regexMatchData;
  12: }

Then, I took the same method in its original (crappy) form, and translated it to VB to see what ReSharper would do.  Here’s the method again, VB this time:

   1: Private Function GetRealFieldData(ByVal regexMatchData As String) As String
   2:     If regexMatchData.Length = 10 Then
   3:         Return regexMatchData.Substring(1, 8)
   4:     ElseIf regexMatchData.Length = 9 Then
   5:         If System.Text.RegularExpressions.Regex.IsMatch(regexMatchData, "^\D") Then
   6:             Return regexMatchData.Substring(1)
   7:         Else
   8:             Return regexMatchData.Substring(0, 8)
   9:         End If
  10:     Else
  11:         Return regexMatchData
  12:     End If
  13: End Function

Even uglier than it was in C#, but I guess that depends on who’s looking.  Here’s the view in my IDE:

ResharperVb1

Wow, that’s quite a difference!  Aside from the method signature (VB console apps default you to Module1.vb rather than program.cs, so static/shared isn’t an issue here), none of the stuff that was marked by ReSharper in the C# version of this method is marked in the IDE for a VB application.  However, the light bulbs still do show up, I just had to move through line by line to see them.  ResharperVb2 Going to the ElseIf statement brings up a bulb offering to change the if statement to a select case statement, but nothing is said about converting unnecessary else’s to returns.  Also missing is the option to convert the Regex.IsMatch() condition to an If/Iif statement, my favorite part of the C# example.

So I guess the added support for VB in ReSharper 4.5 still lags well behind the power this plug-in provides for C# programmers.  And you know what?  I don’t blame JetBrains at all.  I believe that ReSharper is as much a best practices tool as it is a productivity tool.  When it comes to .Net best practices in books and online, a huge percentage of the examples you see are in C# rather than VB.  I applaud Microsoft for supporting both languages as .Net moves forward, even though VB has been behind in several language features, but why would JetBrains spend a great deal of time and money integrating VB support into ReSharper when the majority of the developers that use their product are coding in C#?  I have many more theories on this, which I’m sure I will expand on in days to come, and I’m hoping that I find ways to make ReSharper a better tool for VB coding.  But for elegance, productivity, and best practices, the true value of this tool is still found in C#.

Be the first to rate this post

  • Currently 0/5 Stars.
  • 1
  • 2
  • 3
  • 4
  • 5
Tags:  
Categories:   C# | Tools | VB | Visual Studio
Actions:   E-mail | del.icio.us | Permalink | Comments (4) | Comment RSSRSS comment feed

We All Laugh in the Same Language

Wednesday, 28 January 2009 15:09 by aj

As I've continued coding in VB.Net at my new(ish) job, the "WTF!!!" factor has reduced substantially, although I still do a lot of backtracking to insert Dim statements.  For the most part, I've realized I can do all the same stuff in VB that I did in C#, along with a couple of nice things like the great pile of VB snippets that ship with Visual Studio compared to the meager offerings for C#.  Don't get me wrong, I'd still rather be coding C#, but I've come to terms with the fact that they really are the same thing when it comes down to the CLR, and except for a few small differences, it's really just a matter of personal preference.

Or is it?

It's certainly not my personal preference, in this case.  So I guess it's enterprise preference.  But wait, who decides enterprise preference?  Someone obviously does, someone who probably makes a helluvalot more money than I do, and probably doesn't code any more if they ever wrote code in the first place.  What I've been wondering lately is this: if both VB and C# compile and run on the same .Net runtime, why do enterprises care which language its developers use to write .Net applications?  Just because I've been coding VB for the last three months doesn't mean that my C# skills have atrophied off like an unused extremity.  I can still read and write C#, and when I coded C# for a living ("enterprise standard" at my old job) I could still read and write VB.  Once folks understand the simple syntactic differences between the two, square brackets for arrays, angle brackets for generic type identifiers, "Dim thing as type," Function and Sub, etc., it's really not hard at all to read and understand both.

The common answer I hear to this question is that the enterprise wants everyone coding in the same language to...

  1. Promote code reuse.
  2. Make it so that if department A happens to be on a team building exercise at the archery range and they all get impaled on crazy boomerang arrows, department B can "seamlessly" pick up where the dead folks left off.

 

Superficially, these reasons make a lot of sense.  Code is easier to share and recycle if it's all in the same language.  Joe Developer coding VB in the Wonky Department on the 12th floor can read Jane Developer's code, even though she works on entirely different stuff in the Hinky Department on the 3rd floor.  And that's good, because Jane wrote a really cool snippet for connecting to the company mainframe and screen-scraping something or other.  But wait...why does Joe even need to read Jane's code?  It seems to me that if Jane wrote that functionality in C#, she can simply bundle it up into an assembly, compile it, and offer it to Joe as a referenceable DLL. 

OMG! But that DLL was written in C#!

All Joe sees are the members of Jane's object after he references, and Visual Studio translates that to VB for him anyway. 

IntelliSense even formats the tooltips in VB

 

Joe doesn't even see "public string CSharpMethod(string inVal)."  Pretty nifty runtime conversion there, if you ask me.  Another example of the inherent quality built into the Visual Studio IDE.

Can somebody please tell me why I can't write my applications in C# even though my boss wrote applications in VB?

Be the first to rate this post

  • Currently 0/5 Stars.
  • 1
  • 2
  • 3
  • 4
  • 5