# Wednesday, 18 July 2007

I decided a while back that I had too much extraneous junk running on my development machine and it was time to scale back.  Fist to go were Google Desktop, and Microsoft Desktop Search, both of which had been competing to see who could eat the most cycles and thrash my drives the worst.  Next on the list was TortoiseSVN.  Tortoise's cache seemed to be eating an awful lot of CPU time.  "How ever will I manage to deal with SVN without it?", I found myself wondering.  The reply came back "have you become completely feeble in your old age? Once you lived by PVCS, before there was such a thing as a decadent SCC GUI!". 

So I figured I'd give it a go.  The results have been pretty good so far, although it has taken me a while to get used to the svn.exe command set.  On the up side, it seems much faster than Tortoise, with updates in particular taking much less time.  The thing I find myself missing the most if the commit dialog, where you can uncheck stuff you don't want to commit right now.  Living without that makes for some extra typing, but overall it's still worth it.

The one thing that's a major hassle is browsing the repository.  If I have to figure out where someone shoved something in which repository, I've been falling back on another machine with Tortoise installed.  Lame?  Possibly.  I couldn't find anything approximating a non-Tortoise GUI SVN repository browser.  Maybe there is one, and I just haven't heard. 

So overall, I'm not quite ready to go back to edlin for text files, but the svn command line is treating me pretty well.  We'll see if I ever come to some watershed event where I decide to go back to the GUI.  That day may well come, but it's not on the horizon just yet.

Wednesday, 18 July 2007 10:57:58 (Pacific Daylight Time, UTC-07:00)  #    Disclaimer  |  Comments [10]  | 
# Monday, 09 July 2007

I haven't had a whole lot of time for either lately, but have squeezed in a few. 

Books

  • I'm in the midst of Scott's copy of Barry Eisler's Killing Rain.  Good fun, as always
  • I'm about half way through Herman Melville's Typee, about his jumping ship in the South Pacific.  Quite the adventure story, and much quicker pacing than the Melville I've read before (i.e. Moby Dick)
  • Sandor Ellix Katz's The Revolution Will Not Be Microwaved.  A very informative read about the state of the "underground" American food revival.  There are a lot of people out there trying to reclaim traditional and sane eating practices.  Good to know.
  • I just finished Carl Hiaasen's Tourist Season.  He can do no wrong as far as I'm concerned, and I've loved every hilarious thing I've read of his.

Movies

  • Less to tell here, I'm afraid.  Not too much has wowed lately
  • I finally saw 300, and it blew.  Totally.  Very sad.
  • My favorite of late has been Road to Perdition.  I never would have thought I'd believe Tom Hanks as a gangster, but it was a great film.  Fantastic camera angles, interesting cast, great script.  Well done.
Monday, 09 July 2007 14:30:30 (Pacific Daylight Time, UTC-07:00)  #    Disclaimer  |  Comments [0]  | 

Lately we've been experiencing one of the downsides of all the tooling we've put into our continuous integration practice.  It's fragile.  Trying to get all your tools lined up with versions that all get along is tricky, and hard to keep balanced.  Particularly when two of them (NCover and TypeMock) both try to register themselves as profiles, and have to be chained to keep the tests running while gathering coverage information.

I think we've just about got everybody moved up to the right versions, but there's been lots of "it works on my machine" the last week or so. 

The price you pay, I guess.

Monday, 09 July 2007 14:15:03 (Pacific Daylight Time, UTC-07:00)  #    Disclaimer  |  Comments [0]  | 
# Friday, 29 June 2007

I've touched on this before, but I'd like to expound some personal theories (or preferences) on exception handling in C#.  There are plenty of things to debate here, but this is what I believe.

There are a few assumptions I make about code to which these exception handling rules apply, and I'll try to make those assumptions evident as I go along.

  • Method names are verbs.  I'm big on verbs and nouns in code (which, I recently learned, makes me a fan of "Domain Driven Design").
    • If my method is supposed to transfer money from one back account to another, it should be called Transfer
    • If my method can't fulfill it's contract (in the form of it's verb) it should throw an exception.  If Transfer can't transfer, it should throw an exception.  Period.
      • Don't worry about whether the error is really "exceptional".  If it was really exceptional, you wouldn't catch it (see below).
  • Catch only exceptions you know how to handle, and be specific.
    • Don't catch System.Exception.
      • If you don't know ahead of time what the exception is going to be, you don't know how to handle it, and you should send it up the stack.
      • Catching System.Exception means trying to deal with the really exceptional case, which by definition you can't plan for.
  • Write your own application specific Exception classes, and write lots of them
    • Make exceptions as specific as possible
      • if I'm writing Transfer, and there isn't enough money in the source account to fulfill the request, throw an InsufficientFundsException, not ArgumentException or ApplicationException, or InvalidOperationException.
    • Hide implementation specific exceptions by wrapping them in custom exceptions.
      • If you are writing a configuration system, and in your initialization routine you look for an XML config file, and that file isn't there, don't throw FileNotFoundException.  Wrap the FileNotFoundException in your own ConfigurationInitializationException.
        • The consumer of the configuration system doesn't care about your config file, they just care that you failed to initialize.
        • The ConfigurationInitializationException should be part of your contract to the outside world, and they should plan to catch that, not FileNotFoundException.
        • If you change the config system to initialize itself from the database instead of an XML file, and the database isn't there, your consumer doesn't have to worry about DbNotFoundException, just your custom exception according to your contract.
    • Make your custom exceptions part of your contract
      • In Java, you can make that compile-time checkable.
      • In .NET, you can include the exception in your XML documentation using the <exception> element.  It's not enforceable, but at least it's documented.
    • Make sure your custom exceptions are serializable and implement the right constructors
      • VS 2005 has a template that generates good exception classes (type exception->tab)
    • There may be some very specific reasons for catching System.Exception (but I don't really believe that)
      • If you must, never catch Exception without throwing something else.
        • If you don't care if your code failed, why did you write it?  That probably points to a design problem.
      • If you find yourself arguing for catching Exception, you probably have a design problem.
        • There are real reasons for crashing your application.  If nobody knows how to handle an exception, should you really keep going?  Or just take your lumps and quit?
        • If your application writes to the database, and the database isn't there, should you keep logging errors, or just exit the application?  (This depends on how transient the problem is, etc., and I'm probably ratholing here so you get it, right?)

YMMV, but there you go.

Discuss.

Friday, 29 June 2007 11:54:55 (Pacific Daylight Time, UTC-07:00)  #    Disclaimer  |  Comments [4]  | 
# Tuesday, 26 June 2007

A while back I posted about how we're implementing denials using AzMan.  This week, a helpful reader pointed out that with a little extra math, I could save a call into AzMan (with all the attendant COM interop, etc.).

So, instead of my previous

 

object[] grantOps = new object[] { (object)1, (object)2, (object)3, (object)4};

object[] denyOps = new object[] { (object)100001, (object)100002, (object)100003, (object)100004 };

 

 

object[] grantResults = (object[])client.AccessCheck("check for grant", scopes, grantOps, null, null, null, null, null);

object[] denyResults = (object[])client.AccessCheck("check for deny", scopes, denyOps, null, null, null, null, null);

 

for (int i = 0; i < grantResults.Length; i++)

{

    if(((int)grantResults[i] == 0) && ((int)denyResults[i] != 0))

        Console.WriteLine("Grant");

    else

        Console.WriteLine("Deny");

}

 

I can do it in one call like so

object[] allOps = new object[8];

grantOps.CopyTo(allOps, 0);

denyOps.CopyTo(allOps, 4);

object[] allResults = (object[])client.AccessCheck("check for grant and deny", scopes, allOps, null, null, null, null, null);

for(int j = 0; j < grantOps.Length; j++)

{

    if (((int)allResults[j] == 0) && ((int)allResults[j + grantOps.Length] != 0))

    {

        Console.WriteLine("Grant");

    }

    else

        Console.WriteLine("Deny");

}

 

It does mean you have to be a little careful about getting the indexes straight, but that's probably worth the savings you'll get by not making the extra COM call. 

Every little bit helps...

AzMan | Work
Tuesday, 26 June 2007 09:12:39 (Pacific Daylight Time, UTC-07:00)  #    Disclaimer  |  Comments [3]  | 
# Friday, 15 June 2007

Update: this seems to work best in RSS, so I'll go with it for now.  Copy as HTML from VisualStudio 2005, then Paste Special with the Keep Formatting option in Live Writer.

This is another method of inserting code...  I'm mostly just testing, so bear with me.  This is using the "Copy as HTML..." from inside VS.NET, then using the new Paste Special... in Live Writer.

[DataContract]

public class BankUser : UserBase

{

    public BankUser() : base() { }

 

    [DataMember]

    public int TupperwarePoints;

 

}

Friday, 15 June 2007 13:16:00 (Pacific Daylight Time, UTC-07:00)  #    Disclaimer  |  Comments [3]  | 

Hmm.  I switched from a previous "Insert Code" plugin for Live Writer to a "Paste from Visual Studio" plugin for those last couple of code samples.  They look better on the web page, but even worse in the RSS.  Sigh.  Back to the drawing board.  If you can't decipher the code, please have a look at the HTML until I find a better solution.  Sorry RSS users...

Friday, 15 June 2007 13:11:39 (Pacific Daylight Time, UTC-07:00)  #    Disclaimer  |  Comments [0]  | 

I think I've come across a better solution (or at least one that I'm happier with) to this problem.  Turns out that the KnownType attribute can take a method name instead of a type.  The type it's applied to then has to implement a static method with that name that returns an array of Type.  That method can then decide which types to return.  So I could do something like this

[DataContract]

[KnownType("CheckForConfiguredOverrides")]

public class UserBase

{

    [DataMember]

    public string FirstName;

    [DataMember]

    public string LastName;

 

    public static Type[] CheckForConfiguredOverrides()

    {

        List<Type> result = new List<Type>();

 

        string thisTypeName = typeof(UserBase).FullName;

        string overrideType = System.Configuration.ConfigurationManager.AppSettings.Get(thisTypeName);

        if (!string.IsNullOrEmpty(overrideType))

        {

            Type type = Type.GetType(overrideType);

            if (type != null) result.Add(type);

        }

 

        return result.ToArray();

    }

}

Then in the config file (this ultimately will use our distributed configuration service) I add

<appSettings>

  <add key="UserBaseType.UserBase" value="UserBaseType.BankUser"/>

</appSettings>

 
To return the right type.  Everybody is happy!  As a side benefit, this allows me to limit "overridability" to only those types I apply the attribute to.  That lets me (as the designer) decide which types are OK to subclass and which aren't (obviously I could use sealed here as well, but that's a separate issue) using this KnownType attribute.  I think this will work out much better than marking up base classes with specific types.

Indigo | Work
Friday, 15 June 2007 12:43:46 (Pacific Daylight Time, UTC-07:00)  #    Disclaimer  |  Comments [0]  | 

This may have been understood by the set of all people not me, but I didn't realize that the KnownType attribute doesn't seem to work on a MessageContract.  The KnownType attribute is supposed to tell the data contract serializer that there might be some extra types it needs to know about when serializing your objects.  It's equivalent to the XmlInclude attribute used by the XmlSerializer.  If I have some code that looks like this...

[MessageContract]

public class UserRequest

{

    [MessageBodyMember]

    public string UserName;

    [MessageBodyMember]

    public bool SendExtended = false;

}

 

[MessageContract]

public class UserResponse

{

    [MessageBodyMember]

    public string Message;

    [MessageBodyMember]

    public UserBase User;

}

 

[DataContract]

public class UserBase

{

    [DataMember]

    public string FirstName;

    [DataMember]

    public string LastName;

}

 

[DataContract]

public class BankUser : UserBase

{

    public BankUser() : base() { }

 

    [DataMember]

    public int TupperwarePoints;

 

}

In my server side implementation, if the "SendExtended" flag is true in the UserRequest, the object returned in the "User" property of the UserResponse is a BankUser, not a UserBase object.  If the code runs like this, that fails horribly, since the data contract serializer is set to serialize a UserBase, not a BankUser. 

I would have thought that I could mark up the UserResponse, like so

[MessageContract]

[KnownType(typeof(BankUser))]

public class UserResponse

{

    [MessageBodyMember]

    public string Message;

    [MessageBodyMember]

    public UserBase User;

}

Turns out this totally doesn't work.  I get the same serializer error, despite the KnownType attribute.  If I make UserResponse a DataContract instead of a MessageContract, it works fine, and the appropriate BankUser object is received on the client side. 

However, in my actual code, I need the MessageContract.  The alternative is marking up the UserBase class itself, like this:

[DataContract]

[KnownType(typeof(BankUser))]

public class UserBase

{

    [DataMember]

    public string FirstName;

    [DataMember]

    public string LastName;

}

This works just fine, but from a design standpoint it's teh suck.  This means that I have to tell my base class about all it's derived types, thus defeating the entire point of inheritance.  That's why I never used the XmlInclude attribute.  I might have to rethink how the messages are composed and see if there's a better way to encapsulate things.

On a slightly unrelated note, it seems that my ServiceHost takes much longer to start up when the Request and Response are defined as MessageContract than when they are straight DataContracts.  I haven't tested this extensively, so it's anecdotal, but interesting nonetheless. 

Indigo | Work
Friday, 15 June 2007 10:37:14 (Pacific Daylight Time, UTC-07:00)  #    Disclaimer  |  Comments [2]  | 

Check out the latest Hanselminutes to hear Scott and I chatting with Carl about the latest language features in Visual Studio 2008 ("Orcas"), static vs. dynamic languages, and whatever else came up.

There are some very cool features coming up in C# 3.0, which while they are there mainly to enable LINQ, provide a number of opportunities for reducing the amount of extra code we write, and enabling a closer link between code written and developer intent.  Pretty exciting stuff.

Radio | Work
Friday, 15 June 2007 09:34:34 (Pacific Daylight Time, UTC-07:00)  #    Disclaimer  |  Comments [1]  |