Brad Abrams — API design hall of shame

Brad thinks the API AppDomainSetup.ShadowCopyFiles is API design hall of shame.

I don't think Brad is fair here. At best, it is just a not-so-well-designed API.

An API to be hall of shame should at least have one of the following problems:

1. An API can never be used.
2. An API that nobody can figure out what it does, nor how to use it.
3. An API that nobody uses (or knows, cares)
4. An API that damage a design completely.


AppDomainSetup.ShadowCopyFiles is far from any of those.

Comments (6)

  1. David Betz says:

    First off, Brad says it. That settles it.

    Secondly, see the first one. Brad is the man, he knows API better than anyone. He writes the rules about what is good and what is bad. By disagreeing with you, you are BY DEFINITION wrong.

  2. I think it satisfies number 4 to a T.

    Using a string to represent a boolean when the language supports booleans natively is enough to qualify you for the daily wtf.

  3. Jeff Parker says:

    I agree, there are much worse in the frame work. The undocumented ones are the one that really erk me. I have used this API before and actually use it quite often. I will admit I thought it was odd that it took a string saying true or false but hey it was documented.

    2. An API that nobody can figure out what it does, nor how to use it. <<<< There are quite a few of those in there.

    Another one I stumbled across the other day.

    Ok Great, A nice big public API. But Don’t use it and no documentation on what it does or is. Actually I am half thinking this is a class I need and am going to end up writing on my own. I need a config file for a class library.

    3. An API that nobody uses (or knows, cares) <<< Link above. Another prime example no one knows it, it isn’t documented, so why do I care it is there. There are a bunch of these public classes that are there in the framework we are not supposed to use. So why are they there and not private or Internal.

  4. Ok, well by that criteria:


    Fits the bill perfectly. (i.e. you can’t use it in any real scenario because if you bind it to a database field that allows null it crashes.)

    Response.RewriteURL(…) in .NET 2.0 fits nicely too because if you turn it on, then you’ll get a crash in the root of the web site (i.e. (without any file name) will crash. I found a work around, but it’s ugly and results in a redirect happening). Oh ya, and then there is the added functionality to reset the ~/ path to the right one for the client browser query… but it doesn’t work so you have to use V1.1 version, but if you do that, then the form IS repathed, just nothing else so you can’t manually fix them.

    There are serveral others in .NET 2.0 ASP.NET that I’ve found but hey, I’ve reported them as bugs and gotten nowhere.

    My personal favourite is the Developer Debug web server… great idea! But why the F*ck would you put it in a sub directory when every project gets it’s own server????? If I was working on a virtual directory I should be able to specify the path that it will use, otherwise it should use the root. All this thing does is make developing sites very hard (i.e. masterpages and relative pathing is a nightmare) so you just go back to using IIS very quickly.

    To name a few…

  5. Mark Scambary says:

    I’m leaning towards Brad’s view of things. I can accept the boolean/string thing but the clincher for me is the inconsistant

    behaviour when setting the property to "false". Here’s the code I’ve used to get a predicatable result…

    // Enable shadow copying – yes, this is a string value of "true" or "false".

    // NOTE: –> There is some inconsistancy here. If CachePath is set to a directory then even setting ShadowCopyFiles

    // "false" will still enable shadow copying. So to safely disable shadow copying leave both CachePath and ShadowCopyFiles null.

    if (shadowCopyFiles)


    setup.ShadowCopyFiles = "true";

    setup.CachePath = pluginDirectory;


Skip to main content