Ross Coded Classes

October 3, 2010

Programmer Expectations

Filed under: Programming — Tags: — Ross Bradbury @ 4:09 pm

Here are a few things that I have thought about and expect from programmers, whether they are on my team or not. I have tried to be honest with myself and really think about what I have written. I hope that readers will use these thoughts constructively to find something they can improve upon in their work as programmers or otherwise, either from what I have said or some thought of your own that my words sparked.

-Ross Bradbury

Don’t Reinvent the Wheel

Search for similar functionalities that already exist in the solution. This pertains to functions, user interface, data constraints etc. Building something from scratch should not be the first option even though it is often the most fun.  Reuse existing practices, controls or code when possible. The amount of time spent searching for similarities should be proportional to the complexity of the new work. Include our own code base and third-party code bases that we already use.  Also consider third party solutions we don’t already use for non-trivial functionality. Do not hesitate to ask other team members if they know of similar functionality within the application already, but please do perform a search of the resources you know on your own first.

Consider Uses and Contracts (Explicit and Implied)

Search for all uses of members, classes, controls, components, database views, table schema etc that have been modified in such a way that the existing contract has been changed.  This requires critical thinking about what can be considered a contract, for example:

  • Could a function never return null before, but now it can?
  • Did dependency on string casing change in a way that wasn’t clearly a bug fix?  Even if it was a bug fix, does anything depend on the prior behavior?

Follow the tentacles in order to be as confident as reasonable that changes will not cause something else to break.

Know, Understand and Test Your Changes

Examine and understand all code differences, including changes in designer-generated code, before committing changes (checking them in). If you do not know why the change happened, it is likely it was accidental.  More often than I expect files get checked in that should not have been changed (for example .sln, .vsmdi, .reSharper) or do not compile. Be careful to understand not only what the code does, but how the code works – there is a difference between syntax and semantics.   Knowing what the code does keeps you out of the realm of cargo cult programming.

The compiler is not a code tester – every error the compiler finds can be used as a personal indicator that there are more errors remaining even after the code compiles.  It also isn’t the most efficient use of time waiting for the compiler.  Ideally high-coverage unit tests should be written to test the new code.  Either with or without unit tests, make sure that all of the code has executed before checking in changes – manually cover the code in that case, for example by setting breakpoints and removing the breakpoints as you hit them.  Too often when looking at code from a bug report, code is found to handle a rare condition that couldn’t possibly have ever executed successfully even though it compiles – it was code that was never been run before it was checked it.

Do Not Use a Shotgun to Kill Bugs

When fixing bugs (or really when changing any existing code) it is important to understand all of what the existing code does.  Not every bug can be reproduced in running code but that may actually be a positive thing.  It should be possible to see where the code can go wrong and understand why it happens, but it may take time and practice to develop the skill. Fixes should be justifiable.  For example, fixes checked in with comments like “this should probably fix the crash,” or preventing a null reference by skipping the code if the reference was null without understanding why or how the reference is null are not the correct solution and just end up moving the bugs to different places.  Do not re-write, re-implement or re-factor code that you do not understand and do not know the requirements of; doing so will only move the bug or create new bugs.

Attention to Detail

This is listed as a requirement on just about every job posting I’ve ever read, but sometimes it isn’t easy to understand what it means.

Proofread

One of the things attention to detail means to me is that the same care given to the actual code is also given to everything else – specifically including all comments, whether in code or in changeset notes.  Typographical errors (slips of the hand or finger) found in comments could be taken as an indication of carelessness and I feel they have the potential to significantly reduce trust in the quality of code.  While spelling,  grammar and punctuation mistakes can be errors of ignorance (impossible to catch by the original author,) the majority of typos can be found by a single proofread.  If comments aren’t proofread, was the code?

Create and Maintain Documentation

Document code where it seems non-trivial to understand what is going on. When changing code, double check the documentation of the modified members and class for accuracy.  Comment changes committed to source control with more than just what bug number it fixed – explain a tiny bit about what changed, preferably why if possible.  It is an art to balance what comments go in the source code and which go in the source control comments.

Ask Why? and Consider the Problem Being Solved

Consider the problem being solved by the requested feature or change rather than just jumping straight to coding. Consider what the problem is separately from exactly how the analyst has asked for it to work (why vs. how.) Discuss with analyst your understanding of the problem to confirm that you understand. Once you understand what the problem is and why the analyst has requested the feature work the way it does, you have a much better chance at how to do it with the best design. It is best to do this as early in the design as possible because your input is likely to influence the design. Even if the design seems finalized, programmers can often come up with scenarios that were not considered. Do not be afraid of suggesting simplifications to the design, but offer these as suggestions rather than complaints. Be prepared to have your suggestions turned down but use it as an opportunity to learn more about what and why; it is likely that a simpler approach may have already been considered but was not documented as to why it was not good enough.

As you consider the design, try to think critically about what can happen if the system is used in ways other than what the analysts think the normal use will be.  It is very tempting to jump in and implement what was asked for. The skill of taking some time to think critically to identify problems while they are easier to avoid is applicable to almost everything.

March 1, 2010

Typesafe access to nullable DataColumns

Filed under: .NET Tips — Tags: , — Ross Bradbury @ 3:26 pm

I recommend using these standards when reading values from a DataRow.

  • Prefer not to use the as operator with the DataRow indexer because it hides type conversion errors and it is slower than other options.
  • Use the Field extension method from System.Data.DataSetExtensions.dll for value-type columns that allow DBNull.
  • Use casting for columns that do not allow DBNull.
  • Prefer checking DataRow.IsNull and casting for nullable reference types

The extension methods Field and SetField are in System.DataSetExtensions.dll (System.Data namespace).

// Instead of using the as operator to access a DateTime? type column...
var entryDate = row["entry_date"] as DateTime?;
// Use the Field extension method instead.
var entryDate = row.Field<DateTime?>("entry_date");

All the signatures that the DataRow indexer accepts are accepted by the Field method.

It really is more of a type-safety and understanding/clarity issue than performance. Timings for 50 million calls (I recommend uses in blue) :

DateTime, AllowDBNull = true, not-null:

 row.Field<DateTime?>(column)                        4172 ms Type-safe and fastest
 row.IsNull(column) ? null : (DateTime?)row[column]  9722 ms
 row[column] as DateTime?                            9025 ms Hides InvalidCastException

DateTime, AllowDBNull = true, null:

 row.Field<DateTime?>(column)                        3935 ms Type-safe and pretty fast
 row.IsNull(column) ? null : (DateTime?)row[column]  3080 ms
 row[column] as DateTime?                            5429 ms Hides InvalidCastException

DateTime, AllowDBNull = false, not-null:

 row.Field<DateTime>(column)                         4639 ms
 (DateTime) row[column]                              2708 ms Type-safe and fast

String, AllowDBNull = false, not-null:

 row.Field<string>(column)                           3362 ms
 (string) row[column]                                1317 ms Type-safe and fast

String, AllowDBNull = true, not-null:

 row.Field<string>(column)                           3467 ms less to type, typesafe, slower.
 row.IsNull(column) ? null : (string) row[column]    2106 ms A lot to type, but fast
 row[column] as string                               1320 ms Hides InvalidCastException

String, AllowDBNull = true, null:

 row.Field<string>(column)                           2857 ms less to type, typesafe, slower.
 row.IsNull(column) ? null : (string) row[column]    1182 ms A lot to type, but fast
 row[column] as string                               1279 ms Hides InvalidCastException

September 1, 2009

DataRow.IsNull(column) is preferred over testing for DBNull.Value

Filed under: .NET Tips — Tags: , — Ross Bradbury @ 12:27 pm

Please try to use the IsNull method on DataRow to determine if a value is null or not. DataRow/DataColumn does not actually store null or DBNull – it has a BitArray that says whether or not a non-null value is stored in which columns in the row.  Retrieving the column’s value for the row creates a copy of the DBNull.Value structure which doesn’t get created when calling the IsNull method.  Ideally this performance difference is never observable, but I feel it does tend to make the code cleaner and is the more correct implementation.


// This is better than any of the many possible 
// variations of checking the value

myDataRow.IsNull(someColumnName)

// discouraged

myDataRow[someColumnName].Equals(DBNull.Value)

myDataRow[someColumnName] == DBNull.Value

myDataRow[someColumnName] is DBNull

!(myDataRow[someColumnName] is Int32) // (or appropriate type)

September 23, 2008

Using ReSharper 4.1 to edit C# XML Documentation Comments

Filed under: .NET Tips — Tags: , — Ross Bradbury @ 9:57 am

This is a repost of this one updated to use ReSharper 4.1…

I have recently been working on improving some of our code documentation.  I’ve found ReSharper to be very helpful in this area. (I’m using ReSharper 4.1 with the “Visual Studio” keyboard shortcuts.)
 
ReSharper’s Surround With Templates
 
I find a lot of places where paragraphs (<para>) need to be inserted, or where a member or class has been referenced by name only, and a reference using the <see> tag would be better.  One thing that I have found extremely helpful is to add my own “Surround With” templates in ReSharper.  Now I just have to highlight the text that I want to be in its own paragraph, and press Ctrl+E, U, D.  If I want to change a member name to a see tag I press Ctrl+E, U, E or use the ReSharper | Code | Surround with… menu and select the template I want.
 
Adding your own templates to ReSharper is easy:
  1. Navigate to ReSharperLive Templates… | Surround Templates.
  2. Expand User Templates.
  3. Expand C#.
  4. Click the New Template toolbar button.
  5. Fill in a Description.
  6. Choose where it will be Available by clicking the hyperlink.  For these XML code documentation comments, I choose Language-specific for C# and check Everywhere (everywhere because none of the other options seemed to work for the comments.)
  7. Edit the template text to wrap $SELECTION$ with the text you want.
  8. Choose OK.
  9. If you like, you may now choose a position for your new template in the quick access list to choose which letter it can be accessed by.  Drag your template into the list on the right to choose a shortcut.

Here are some of the Surround With templates I’ve set up for editing documentation comments:

Name Template Text
<para>
<para>$SELECTION$</para>
<see>
<see cref=”$SELECTION$”/>
<see> label
<see cref=”$SELECTION$”>$SELECTION$</see>
<note> <note type=”caution”>$SELECTION$</note>
 
I’ve found that using the template to insert the <see> tags sometimes cause ReSharper or Visual Studio to incorrectly complain that the code won’t compile by highlighting it; I can usually work normally, but if I get tired of the squiggly lines or if it gets too confused I just close the file and open it again.  I find this to be a minor inconvenience compared to the amount of time it saves.
 
ReSharper’s Live Templates
 
If you want to be able to insert text with ReSharper but you don’t want the text to surround the selection, you can use a Live Template.
 
Adding your own templates to ReSharper is pretty easy:
  1. Navigate to ReSharper | Live Templates | Live Templates.
  2. Expand User Templates.
  3. Expand C#.
  4. Click the New Template toolbar button.
  5. Fill in an shortcut and description.  (I usually set the description to the same thing as the template text since these are usually small.)
  6. Choose where it will be Available by clicking the hyperlink.  For these XML code documentation comments, I choose Language-specific for C# and check Everywhere (everywhere because none of the other options seemed to work for the comments.)
  7. Edit the template text you want to insert.
  8. Choose OK.

Here are some of the Live templates I’ve set up for editing documentation comments:

Abbreviation Template Text
seet
<see langword=”true”/>
seef
<see langword=”false”/>
seen
<see langword=”null”/>

June 17, 2008

Pop Quiz #1 Answer

Filed under: .NET Tips — Tags: , — Ross Bradbury @ 12:30 pm
You want to read the question first.
 
In this case, the bug in the code has to do with overflow exceptions.  The value of the GetHashCode() method that all objects have can return any Int32 value, ideally there is no less chance that it returns Int32.MaxValue or Int32.MinValue than the chance that it will return a smaller number like 5.  Doing arbitrary math with the result of GetHashCode() when the code is compiled as checked can easily cause an OverflowException.
 
Even if the code were unchecked and the wrapping behavior was expected and desired, it is still not clear to someone reading the code that you want it do that.

// Throws System.OverflowException if
// ServiceName.GetHashCode() is large enough.
public override int GetHashCode()
{
      return ServiceName.GetHashCode() + DbId;
}

// Explicitly decide to let the overflow wrap
public override int GetHashCode()
{
      unchecked
      {
            return ServiceName.GetHashCode() + DbId;
      }
}

// Shorter way to explicitly let the overflow wrap
public override int GetHashCode()
{
      return unchecked(ServiceName.GetHashCode() + DbId);
}

June 16, 2008

Pop quiz #1

Filed under: .NET Tips — Tags: , — Ross Bradbury @ 11:37 am

What could be wrong with this class?  Think carefully and post your answer in the comments. 

 

class Something
{
      public string ServiceName { get; private set; }
      public int DbId { get; private set; } 

      public Something(string serviceName, int dbId)
      {
            if (serviceName == null) throw new ArgumentNullException("serviceName");
            ServiceName = serviceName;
            DbId = dbId;
      } 

      public override int GetHashCode()
      {
            return ServiceName.GetHashCode() + DbId;
      } 

      public override bool Equals(object obj)
      {
            Something other = obj as Something;
            return other != null && DbId == other.DbId && ServiceName == other.ServiceName;
      }
}
 

April 30, 2008

Is it faster to cast or call ToString()?

Filed under: .NET Tips — Tags: , — Ross Bradbury @ 1:10 pm

I was wondering if I already knew an object was a string if it was faster to cast it or to call ToString().  I thought it would be faster to call ToString() because casting has to do some type checking while the String class overrides ToString to return itself:


public class String
{
     //...

     public override string ToString()
     {
          return this;
     }
}

By this reasoning, I figured that (a is string && a.ToString().Length < 4000) would be cheaper than (a is string && ((string)a).Length < 4000).  

It turns out they are both six IL instructions:  

Calling ToString  

L_0007: ldloc.0
L_0008: isinst string
L_000d: brfalse.s L_0023
L_000f: ldloc.0
L_0010: callvirt instance string [mscorlib]System.Object::ToString()
L_0015: callvirt instance int32 [mscorlib]System.String::get_Length() 

Casting  

L_0025: ldloc.0
L_0026: isinst string
L_002b: brfalse.s L_0041
L_002d: ldloc.0
L_002e: castclass string
L_0033: callvirt instance int32 [mscorlib]System.String::get_Length() 

So… now what is the cost difference between the castclass operator and the virtual method call to the ToString method?  

Turns out the cast takes about 75% of the time of a ToString call. 


using System;
static class Program
{
      static void Main()
      {
            object o = "a string";
            string a;
            string b;
 
            Boolean r = (o is string && o.ToString().Length < 4000);
            r = (o is string && ((string)o).Length < 4000);
 
            DateTime t = DateTime.Now;
            for (int i = int.MinValue; i < int.MaxValue; i++)
                  a = (string)o;
            Console.WriteLine(DateTime.Now - t);
 
            t = DateTime.Now;
            for (int i = int.MinValue; i < int.MaxValue; i++)
                  b = o.ToString();
            Console.WriteLine(DateTime.Now - t);
      }
}

April 24, 2008

Using ReSharper to edit C# XML Documentation Comments

Filed under: .NET Tips — Tags: , — Ross Bradbury @ 8:23 am
I have recently been working on improving some of our code documentation.  I’ve found ReSharper to be very helpful in this area. (I’m using ReSharper 3.1.)
 
ReSharper’s Surround With Templates
 
I find a lot of places where paragraphs (<para>) need to be inserted, or where a member or class has been referenced by name only, and a reference using the <see> tag would be better.  One thing that I have found extremely helpful is to add my own “Surround With” templates in ReSharper.  Now I just have to highlight the text that I want to be in its own paragraph, and press Ctrl+Alt+J, D.  If I want to change a member name to a see tag I press Ctrl+Alt+J, E or use the ReSharper | Code | Surround with… menu and select the template I want.
 
Adding your own templates to ReSharper is easy:
  1. Navigate to ReSharper | Options | Templates | Surround With.
  2. Expand User Templates.
  3. Click the Create Template toolbar button.
  4. Fill in a name.
  5. Choose where it will be Available by clicking the hyperlink.  For these XML code documentation comments, I choose Language-specific for C# and check Everywhere (everywhere because none of the other options seemed to work for the comments.)
  6. Edit the template text to wrap $SELECTION$ with the text you want.
  7. Choose OK.
  8. If you like, you may now choose a position for your new template in the quick access list to choose which letter it can be accessed by.

Here are some of the Surround With templates I’ve set up for editing documentation comments:

Name Template Text
<para>
<para>$SELECTION$</para>
<see>
<see cref=”$SELECTION$”/>
<see> label
<see cref=”$SELECTION$”>$SELECTION$</see>
<note> <note type=”caution”>$SELECTION$</note>
 
I’ve found that using the template to insert the <see> tags sometimes cause ReSharper or Visual Studio to incorrectly complain that the code won’t compile by highlighting it; I can usually work normally, but if I get tired of the squiggly lines or if it gets too confused I just close the file and open it again.  I find this to be a minor inconvenience compared to the amount of time it saves.
 
ReSharper’s Live Templates
 
If you want to be able to insert text with ReSharper but you don’t want the text to surround the selection, you can use a Live Template.
 
Adding your own templates to ReSharper is pretty easy:
  1. Navigate to ReSharper | Options | Templates | Live Templates.
  2. Expand User Templates.
  3. Click the Create Template toolbar button.
  4. Fill in an abbreviation and description.  (I usually set the description to the same thing as the template text since these are usually small.)
  5. Choose where it will be Available by clicking the hyperlink.  For these XML code documentation comments, I choose Language-specific for C# and check Everywhere (everywhere because none of the other options seemed to work for the comments.)
  6. Edit the template text you want to insert.
  7. Choose OK.

Here are some of the Live templates I’ve set up for editing documentation comments:

Abbreviation Template Text
seet
<see langword=”true”/>
seef
<see langword=”false”/>
seen
<see langword=”null”/>

June 26, 2007

A Hazard of Reimplementing an Explicit Interface

Filed under: .NET Tips — Tags: , — Ross Bradbury @ 12:00 am

When implementing an interface explicitly, it is best to create virtual methods or properties if you ever expect a subclass to need to change the behavior.  Implementing the interface explicitly helps to not pollute the public members of a type, but subclasses cannot reach the superclass’s implementation if they have to reimplement the interface to change the behavior.  Exposing protected methods for the explicitly implemented members would keep the public interface clean while still allowing access by subclasses.
 
Somewhere I read a post from one of the .NET Framework developers that confirmed the superclass’s implementation would be unreachable in situations such as the one below.  You can find more on Google: http://groups.google.com/groups/search?hl=en&q=explicit+interface+base+c%23 

// Reimplementation of explicit interface implementation makes
// superclass implementation inaccessable from subclass.
 
internal class Program
{
      private static void Main()
      {
            I i = new B();
            System.Console.WriteLine(i.Stuff());
            i = new C();
            System.Console.WriteLine(i.Stuff());
      }
}
 
internal interface I
{
      int Stuff();
}
 
internal class A : I
{
      protected int count = 0;
 
      int I.Stuff()
      {
            return 1;
      }
}
 
/// <summary>
/// Normal code can't get there.
/// </summary>
internal class B : A, I
{
      int I.Stuff()
      {
            count++;
            if (count > 100)
            {
                  System.Console.WriteLine("Infinite loop");
                  return -1;
            }
 
            // Doesn't compile, not allowed to use "base" here.
            // return 2 + ((I)base).Stuff();
 
            return 2 + ((I) ((A) this)).Stuff();
      }
}
 
/// <summary>
/// Even Reflection can't get there.
/// </summary>
internal class C : A, I
{
      int I.Stuff()
      {
            count++;
            if (count > 100)
            {
                  System.Console.WriteLine("Infinite loop");
                  return -1;
            }
 
            System.Reflection.MethodInfo stuffMethodOfI;
            stuffMethodOfI = typeof (A).GetInterface("I").GetMethod("Stuff");
            return 2 + (int) stuffMethodOfI.Invoke((A) this, null);
      }
} 

 Output: 


Infinite loop
199
Infinite loop
199 

May 10, 2007

DataView RowFilter Performance

Filed under: .NET Tips — Tags: , — Ross Bradbury @ 9:45 pm
Avoid using the default System.Data.DataView constructor followed by setting the RowFilter property.  When you want to create a System.Data.DataView object and apply a RowFilter, use the DataView constructor that takes the rowFilter parameter.  This eliminates processesing of DataRowView objects that are later removed when the RowFilter property is set.  This is particularly apparent when the DataTable has many rows and the RowFilter eliminates most of them.
 
Note that you will need to specify Sort and DataRowViewState options to use this constructor.  The defaults are an empty string for Sort and DataViewRowState.CurrentRows for RowState.
DataView slowWay = new DataView(table);
slowWay.RowFilter = rowFilter;

DataView fastWay = new DataView(table,
                                rowFilter,
                                String.Empty,
                                DataViewRowState.CurrentRows);
Older Posts »

Blog at WordPress.com.