More servicesWindows Live
HomeHotmailSpacesOneCare
 
MSN
Sign in
 
 
Spaces home  Ceiled's stuffPhotosProfileFriendsMore Tools Explore the Spaces community
View space
Brendan

Ceiled's stuff

March 29

Delegates and helper functions

Delegates serve a very important purpose in .NET, and particularly in .NET 3.5, with its tendencies towards functional programming. LINQ simply wouldn't make any sense without them. Along with the influx of concepts from functional programming into .NET has come a more comprehensive set of built-in delegates useful for helper functions in the form of various overloads for Action<> and Func<> that take their parameters as generic methods without imparting undue semantic implications about how they'll be used (for example, Action is appropriate for use just about anywhere you might want a delegate that returns void and takes no parameters, but ThreadStart implies semantic meaning). One result of this renewed emphasis on the use of delegates as cleanly-packaged bits of logic that can be passed around as first-class objects rather than being restricted to simple event handlers, as they mostly were in the original version of .NET, is that the strongly-typed nature of delegates has become more constricting.

The fact that delegates are strongly-typed is generally a good thing, but it can sometimes get in the way. Consider what is quite possibly the single most common delegate-related pattern in all of .NET:

protected virtual void OnMyEvent(EventArgs e)
{
    if (MyEvent != null)
    {
        MyEvent(this, e);
    }
}

I can't even count how many times I've written code that looked like this, and it frustrates me to no end. Why? Because I get tired of checking delegates for null. I want to write a helper function that will do the null check for me, to which I can simply pass my delegate and the arguments. One could argue that OnMyEvent() serves that purpose, but I want a generic helper function -- I don't want a new one for every kind of function that I may want to invoke.

The trouble is, .NET does not provide any simple way to write such a helper function without sacrificing significant performance. Either the signature of the helper function would need to match the signature of the delegate, or it would need to take an object array and call DynamicInvoke() which, according to my measurements, takes about 1,000 times longer than invoking the delegate directly. That obviously won't do.

Before going into the solution, I probably need to justify the need a bit more. Like I said, the scenario that made me want this solution is pretty trivial. However, it's just one example. Consider the following code:

public void SetUpWeakBinding(BindingList<int> sourceList, BindingList<int> boundList)
{
    WeakReference weakRef = new WeakReference(boundList);

    ListChangedEventHandler listChanged = null;

    listChanged = delegate(object sender, ListChangedEventArgs e)
    {
        BindingList<int> weakList = weakRef.Target as BindingList<int>;
        if (weakList != null)
        {
            SynchronizeLists(sourceList, weakList, e);
        }
        else
        {
            sourceList.ListChanged -= listChanged;
        }
    };

    sourceList.ListChanged += listChanged;
}

I've elided the part that actually synchronizes the lists, because that's not the point. What this function does is set up a listener on sourceList's ListChanged event that will perform some logic to keep the two lists in question in sync. The important bit is that the boundList is stored as a WeakReference, which allows it to be garbage collected. If it gets garbage collected and the ListChanged event fires again, then the delegate is removed from the invocation list entirely, leaving no trace of the garbage-collected list. This code, minus the SynchronizeLists() call, is equivalent to the if check in the earlier example, only much, much hairier. I implemented this logic for ListChangedEvent this time, but what if later I want to hook up a weak listener of some other delegate type? Copy and paste city. Not good.

What I really want is a helper function that will give a listener that I can use to intercept and filter a call to a delegate without having to know the signature of that delegate. This would allow me to write helper functions such as the two described above.

Unfortunately, this requires some pretty hairy code generation, so I'm going to skip posting the actual results for fear of scaring people off. For the purposes of the rest of this post, assume that I have access to these functions:


public static TDelegateType Wrap<TDelegateType>(Func<TDelegateType> action)
    where TDelegateType : class
{
    return Wrap<TDelegateType>(action, null);
}

public static TDelegateType Wrap<TDelegateType>(Func<TDelegateType> action, Action afterAction)
    where TDelegateType : class
{
    return DoIckyCodeGenerationWork(action, afterAction);
}

If I were to implement Wrap<Action<bool>>() statically, it might look like this:

public static Action<bool> Wrap(Func<Action<bool>> action, Action afterAction)
{
    return delegate(bool b)
    {
        Action<bool> realAction = action();

        if (realAction != null)
        {
            realAction(b);

            if (afterAction != null)
            {
                afterAction();
            }
        }
    };
}

The basic idea is that it takes a function which returns a delegate of the appropriate signature, and a function that should be called after the pass-through has occurred. If the first function returns null, then no further action is taken.

Given these helper functions, our original scenario can be implemented in a generic fashion like so:

public static T Ignorable(this T action) where T : class
{
    return Wrap(() => action);
}

Now I'm free to do things like...

action.Ignorable()();

If action is null, Ignorable() will still return a value, and when I invoke that value, it'll do nothing because the first parameter to Wrap() will return null. I can now also implement the more interesting second scenario, like so:

public static U GetWeakListener<T, U>(this T weakTarget, Action<U> unsubscribe,
    Func<T, U> listener)
    where T : class
    where U : class
{
    WeakReference<T> weakReference = new WeakReference<T>(weakTarget);

    weakTarget = null;

    U realListener = null;
    realListener = DelegateHelpers.Wrap<U>(delegate
    {
        weakTarget = weakReference.Target;

        if (weakTarget != null)
        {
            return listener(weakTarget);
        }

        unsubscribe(realListener);
        return null;
    }, () => weakTarget = null);

    return realListener;
}

My code to set up a weak listener that synchronizes two bound lists now looks like this:

public void SetUpWeakBinding(BindingList<int> sourceList, BindingList<int> boundList)
{
    sourceList.ListChanged += boundList.GetWeakListener(l => sourceList.ListChanged -= l,
        (weakList) => (sender, args) => SynchronizeLists(sourceList, weakList, args));
}

Still a bit complicated, of course -- note that the "listener" parameter is actually a function that *returns* the real listener, not the listener itself. The reason for this is that the real listener is likely to need a reference to the weak target, which of course we want to hold onto only as a weak reference. If you were to pass the (sender, args) => ... portion directly, it would end up holding a reference to boundList, which would prevent it from being garbage collected. This is also why the weak target is passed in to that function, because if it referenced boundList directly, then it would never get garbage collected.

So I finally have a simple way to filter and pre-process delegate calls when I don't have control over the code that invokes them. If anyone is interested in seeing the actual implementation of Wrap(), feel free to request it in the comments.

February 05

Software design is hard

Having celebrated my return to blogging with an almost unmitigated stream of vitriol on the subject of software design, I thought it might be nice to spend a bit of time talking about some techniques I like to employ in order to avoid being the subject of such rants myself. Let me state up-front that I am by no means a certified instructor of software design, and that the following advice is based purely upon my own experience. That said, I hope this will prove helpful to someone.
 

Techniques

The hardest part of software design is getting started. Here are some tips and tricks that have served me well in getting past the initial hump quickly.

Code for Today, Design for Tomorrow
Don't just sit down and write the first thing that comes to mind, but don't stress out over every scenario you might ever want to handle either. Find the happy middle ground. My process for getting started on a new project generally goes something like this:

  1. Stub out some simple pseudo-code that might solve a problem, if the classes and functions they rely on existed.
  2. Stub out the objects that the pseudo-code relies on.
  3. Return to step 1 and solve a new problem. Repeat until you're able to come up with a few new scenarios in a row that your stubs can handle with little or no modification, or until you can't think of anything else you might want to do with them.

Note that the emphasis in this process is not on future-proofing or on exhaustively analyzing the full problem space, but on coming up with a good way to get where you want to go. Also note that the focus is on the code that uses the objects you're designing, rather than the objects themselves. A side effect of this is that whenever possible, you should design your interfaces from the outside in, meaning that the first set of objects you design should be the simplest and most outward-facing. You don't want to write the complex inner machinery until you've demonstrated to yourself that the external interface you're working towards will be workable.

This is actually a recursive process...once you've refined the stubbed-out objects in step 2 based on the requirements that you discover by thinking of problems to solve, you can start adding stubbed-out pseudo-code to the objects themselves, assuming that another set of classes and functions exist, and repeat the entire process until your "pseudo-code" relies entirely on classes and functions that already exist.

Iterative Complexity
A good API will have several "views" people can choose to take of it. When you're stubbing out your interfaces, think about who will want to use them, and what sorts of trade-offs between flexibility and simplicity those people will want. I've found that the majority of architectures I've designed expose three levels of complexity:

  1. Superficial: simple objects and helper functions that assist in manipulating them in common ways.
  2. Integrated: when a developer needs to move off the beaten trail a bit, there are more granular objects available that give more flexibility and control.
  3. Extension: when a scenario pops up that the developer didn't think of, there are mechanisms for replacing and extending the default functionality.

A good example of this phenomenon is an object synchronization framework I wrote recently that's intended to simplify the task of keeping data and views of data from multiple sources in sync. Without focusing too much on the details, the three levels at which one can use this framework are as follows:

  1. Superficial: the vast majority of bindings can be accomplished by calling a simple helper function with a name like BindToProperty() or BindValueToValue().
  2. Integrated: there are a variety of objects one can use directly, such as PropertyAdapter or ViewAdapter.
  3. Extension: there are a variety of objects one can inherit from to provide additional functionality, such as Translator or ValueDomainObjectHolder.

Understanding that your code will be seen from different perspectives by different people can also be useful when doing your initial design. The stubbed-out pseudo-code from step 1 becomes your superficial layer, the stubbed-out interface and class definitions from step 2 become your integrated layer, and the internal objects resulting from recursing on the whole operation will guide the creation of your extension layer.

To Thine Own Self Be True
Before you write a class, know what it represents. Know how it relates to the other classes you've already written, and to the ones you plan to write. Keep a list of these representations and relationships so you don't forget and duplicate something. As much as possible, try to avoid allowing equivalent but incompatible representations of the same information to crop up. If you absolutely must have multiple representations, provide method overloads that accept each representation and convert them to the most centralized. A good example of this would be a method with one overload that accepts a string and one that accepts a TextReader, with the string overload simply creating a StreamReader from the filename and passing that on to the second overload.

Guidelines

Techniques and processes are all very well, but what makes a design "clean"? How can I tell if my interfaces are usable? Here are a few guidelines, in no particular order.
 
Don't Fraternize With the Help
Helper functions generally take two forms:
  1. Simple boiler-plate functionality that is completely straightforward but would be tedious to include everywhere, or
  2. A complex mess that you would hate to have to write again.

Either way, they don't belong in the same class as core functionality. Putting them in a static method in a separate class whose name is related to the core class (e.g., Binding and BindingHelper) can help to make clear what functionality is the object's main focus and what is just conveniently-packaged sugar while still maintaining reasonable discoverability. Helper methods especially don't belong on interfaces. Extension methods in C# 3.0 can be extremely helpful here.

Think About Defaults
When designing a base class, always think about default behavior. What should the majority of derived classes do? If a method has a reasonable default behavior, make it virtual. If there's no reasonable default and you want to force every implementer to consider what a method should do in their case, make it abstract. If you can't think of any reasonable defaults, make it an interface.

On the subject of defaults and interfaces, I find that 99% of the interfaces that I write have a reasonable default implementation that 99% of all implementations can inherit from. Remember, interface methods should not be trivially implementable in terms of each other -- if you break this rule (for example, System.ComponentModel.ICustomTypeDescriptor provides both a GetEvents() method that can more or less always be trivially implemented by calling GetEvents(Attribute[]) with null), it becomes even more imperative that you provide a default base class, with virtual implementations of those trivial methods. Nobody likes writing boiler-plate code.

If You've Got It, Flaunt It
Avoid internal virtual or abstract methods at all costs. If you think a method should be virtual or abstract, don't make it internal. Classes that look like extensibility points but whose overridable members are internal make a mockery of extensibility. WPF's TriggerBase class is a great example of this.

Each of these guidelines represents a question that you can ask yourself about your code. "Is this class focused on its core functionality?" "Does the design of this class or interface force people to think about things they shouldn't have to?" "Have I abstracted the guts of my abstract base classes sufficiently that they can actually act as base classes that can be meaningfully extended?" If the answer to any of these questions is no, I suggest that you spend some time figuring out how to change that answer.

February 04

Save a WPF document to an arbitrary format? Yes, please!

I haven't posted here for a while, but today I was thinking, "You know what would be a great way to get back into blogging? A bitter, angry rant about spotty software design," so here we are. Last night I was working on a little side project in an effort to get to know WPF (Windows Presentation Framework, formerly code-named Avalon) a little better, when I found that I had a need to generate a document to report some data that my application had gathered. No problem...drop a FlowDocumentScrollViewer into my window's XAML file, generate a visual tree for it using the very intuitive System.Windows.Documents namespace, and I'm off to the races. My simple test document is displaying dynamically-generated content beautifully.
 
Unfortunately, displaying that document in this application isn't much use...I would like to be able to send it to friends and post it online, but many people don't have .NET 3.5 installed on their machines, for reasons varying from perfectly good ones like a basic distrust of recently-released software, to less understandable ones like sheer laziness, to downright ridiculous reasons such as owning and operating a Mac. The bottom line is, I need to save this thing out to a more universal format than XAML if I want anyone other than myself to see it.
 
A quick search on MSDN reveals the existence of the SerializerProvider, a handy little object capable of returning an extensible list of registered objects that know how to save WPF object graphs into arbitrary formats such as, according to the documentation, "HTML, RTF, XML, XPS, or alternately to a third-party format." This sounds great! A little bit of data-binding later, I had a context menu that would show me the list of these marvelous serializers that would give my application so much flexibility so easily. I click on the button and...one option appears. XPS. If you're wondering, XPS -- XML Paper Specification -- is the native printer format of Vista. It is not a widely-used document format. A more careful reading of the MSDN article reveals that they never claim that any of those formats actually work -- only that they could be implemented using this wonderfully flexible serialization framework they've put together.
 
Let's examine this "framework" for a moment, shall we?
 
Let me just say it up-front: this framework is not good. I think I see why only the absolute bare minimum functionality is provided out of the box...this thing is painful to work with. Implementing ISerializerFactory is quick and painless -- it's just some meta-data properties like the name of your serializer and the default extension for the files you plan to write with it, and a CreateSerializerWriter() method that takes the Stream the user plans to write to and serves as the application's portal into the wonderful world of document serialization and storage.
 
At the application level, the developer simply creates an instance of SerializerProvider, chooses a SerializerDescriptor from the InstalledSerializers list, and then passes the chosen descriptor to SerializerProvider.CreateSerializerWriter(), which takes the target Stream. So far, so good.
 
But where does the magic happen? How does the SerializerWriter actually work? Here's where things start to go to pot.
 
SerializerWriter is an abstract class with 37 members...all of them abstract.
 
You read that right. The document serialization "mechanism" in WPF will provide you with a list of objects that can be used to serialize documents and some basic metadata about them, but provides absolutely no help whatsoever in the actual serialization process.
 
Let's examine these 37 methods. Four of them are actually events (abstract events!? Really?), one of them is CancelAsync() -- yes, the developer of each SerializerWriter is expected to implement cancelling and asynchronous operations themselves; more on that later -- and two more are overloads of a function called CreateVisualsCollator(), which is apparently supposed to be overridden in a derived class to return an object "that writes collated Visual elements." I have no idea what this means and MSDN isn't very helpful, so let's turn our attention to the remaining thirty.
 
Here are six of them:
 
        public abstract void Write(FixedDocument fixedDocument, PrintTicket printTicket);
  
        public abstract void Write(FixedDocument fixedDocument);
  
        public abstract void WriteAsync(FixedDocument fixedDocument, PrintTicket printTicket, object userState);
  
        public abstract void WriteAsync(FixedDocument fixedDocument, object userState);
  
        public abstract void WriteAsync(FixedDocument fixedDocument, PrintTicket printTicket);
  
        public abstract void WriteAsync(FixedDocument fixedDocument);
 
Look carefully...notice a pattern? Yes, the remaining thirty abstract members of SerializerWriter are actually five methods, repeated six times each. If you need to take a moment to read that sentence again, feel free. I can wait. Let it sink in.
 
The pattern above is repeated for FixedDocumentSequence, FixedPage, DocumentPaginator and Visual, and five of those six method overloads are trivially implementable by calling the Write() overload that takes a PrintTicket (the WriteAsync() methods can easily be implemented by using the BeginInvoke() mechanism exposed by all delegates). Furthermore, FixedDocument, FixedDocumentSequence and FixedPage all expose a single DocumentPaginator object, so as far as I can tell, it's perfectly reasonable to provide default implementations of those three that simply call the DocumentPaginator overload. That said, DocumentPaginator can also be reasonably straightforwardly converted into a stream of Visuals. In other words, it's not completely unreasonable to say that all 29 of these 30 abstract methods can be reasonably implemented by calling the remaining method.
 
This sort of thing really burns my biscuits, a phrase which here means "makes me want to strangle someone." Sorry, I just finished the last chapter of A Series of Unfortunate Events.
 
In short, this mechanism consists of a thin wrapper around a set of registry keys, and a class with a ridiculous amount of abstract methods and literally zero built-in functionality. They haven't even given us convenient wrapper methods for firing the events so we don't have to check them for null first.
 
Am I missing something? All in all, I'm extremely disappointed with this feature. Also, MSDN talks about "document serialization and storage," and "storage" seems to imply that it can read documents back from these arbitrary formats into WPF documents -- unless they mean "storage" in the sense of sticking it into a box and never looking at it again -- but I can't find any actual evidence of such functionality, not even a stubbed-out class to provide a common interface to it like SerializerWriter.
 
I'm writing this in the hope that someone who worked on this feature will see this and feel compelled to respond, and maybe explain why this isn't as bad as it seems. Because from here, it looks pretty bad. If that happens, please be assured that if you can convince me that this is the right design, or even not an abysmally terrible design, I'll post an immediate retraction. I just want to know what happened.
 
I want to love you, WPF, I really do, and when I'm working with dynamic styling and templating, or when I data-bind a tree and then decide it would make more sense as a menu item, I do love you; but then you pull out something like this, or you make all the useful methods on TriggerBase, TriggerAction and Expression internal for no apparent reason, or you throw an exception when I try to create a KeyGesture that consists of a letter key and no modifiers (so I can do things like Visual Studio's Ctrl-K, F command). Why won't you let me love you?
October 28

"Fun" with WCF proxy generation

If you're anything like me, you hate typing something in one place and then having to go type it again somewhere else. If you're more than a little like me, you've been using WCF to write service-enabled applications and you've been frustrated by the tools at your disposal to do so. I'm using VS 2005 with the WCF extensions at work and I've seen only two points of IDE integration for working with WCF: Add Service Reference, and Edit WCF Configuration.

The concept of service references makes a lot of sense, but the implementation in the VS 2005 extensions is completely useless if you're authoring your own application, because it requires you to run your service application live when refreshing the service reference, which isn't very practical for automated build systems. Running my server application so that I can update the service reference on my client gets tedious after a while. The VS 2008 beta 2 has an intriguing "Find services in this solution" button on the Add Service Reference dialog, but I haven't been able to get it to do anything. Maybe once this button is implemented, the trick I'm about to describe will become unnecessary.

The Edit WCF Configuration is great for editing service configurations, and it's useful for creating client configuration files as well -- but again, it's a manual process that's not easy to automate. Manual processes are fine for personal projects, but not so fine for projects at work where co-workers and automated build servers need to be able to update things.

The biggest problem that I've been having is that svcutil.exe doesn't seem to use the configuration information when you run it against a service executable, and I just couldn't figure it out. It would just make up some HTTP endpoints instead of using the ones configured for the service. However, while scouring the svcutil.exe documentation, I finally stumbled upon the "/serviceName" option. Aha! A quick test reveals that it gives me exactly what I want: server code and a fully-functional client configuration that doesn't need to be touched manually at all. But I couldn't stop there...I want this properly integrated into MSBuild.

Six hours later, out pops Ceiled.WCF.targets:

<Project xmlns="http://schemas.microsoft.com/developer/msbuild/2003">
  <PropertyGroup>
    <CoreCompileDependsOn>$(CoreCompileDependsOn);BuildServiceReferences</CoreCompileDependsOn>
  </PropertyGroup>
  <Target Name="BuildServiceReferenceProjects">
    <MSBuild Projects="@(ServiceReference)" />
    <MSBuild Projects="@(ServiceReference)" Targets="GetTargetPath">
      <Output ItemName="ServiceReferencePaths" TaskParameter="TargetOutputs" />
    </MSBuild>
  </Target>
  <Target Name="GenerateServiceReferences" Inputs="@(AppConfigWithTargetPath);@(ServiceReference)" Outputs="$(IntermediateOutputPath)Services\%(ServiceReference.Name)\Services.txt">
    <Warning Text="$(FinalAppConfigLocation)" />
    <CallTarget Targets="ForceConfigFile" />
    <Warning Text="$(FinalAppConfigLocation)" />
    <CreateProperty Value="@(ReferencePath->'%(FullPath)', '&quot; &quot;/reference:')">
      <Output PropertyName="ServiceReferenceCommandLine" TaskParameter="Value" />
    </CreateProperty>
    <CreateProperty Value="@(ServiceReference->'%(Namespace)', '&quot; &quot;/namespace:')">
      <Output PropertyName="ServiceReferenceNamespace" TaskParameter="Value" />
    </CreateProperty>
    <RemoveDir Directories="$(IntermediateOutputPath)Services\%(ServiceReference.Name)" />
    <MakeDir Directories="$(IntermediateOutputPath)Services\%(ServiceReference.Name)" />
    <WriteLinesToFile File="$(IntermediateOutputPath)Services\%(ServiceReference.Name)\Services.txt" Lines="%(ServiceReference.ServiceNames)" />
    <Exec Command="for /f %%i in ($(IntermediateOutputPath)Services\%(ServiceReference.Name)\Services.txt) do &quot;c:\Program Files\Microsoft Visual Studio 8\Common7\IDE\svcutil&quot; &quot;@(ServiceReferencePaths)&quot; &quot;/namespace:$(ServiceReferenceNamespace)&quot; /directory:$(IntermediateOutputPath)Services\%(ServiceReference.Name)\%%i &quot;/reference:$(ServiceReferenceCommandLine)&quot; /serviceName:%%i" />

    <Exec WorkingDirectory="$(IntermediateOutputPath)Services\%(ServiceReference.Name)" Command="for /f %%i in (Services.txt) do &quot;c:\Program Files\Microsoft Visual Studio 8\Common7\IDE\svcutil&quot; %%i\*.wsdl %%i\*.xsd /out:%%i.cs &quot;/config:$(ProjectDir)\@(AppConfigWithTargetPath->'$(OutDir)%(TargetPath)')&quot; /mergeConfig" />
    <ItemGroup>
      <ServiceReferenceItemsToCache Include="%(ServiceReference.ServiceNames)">
        <ServiceLibraryName>%(ServiceReference.Name)</ServiceLibraryName>
      </ServiceReferenceItemsToCache>
    </ItemGroup>
  </Target>
  <Target Name="DoBuildServiceReferences" DependsOnTargets="BuildServiceReferenceProjects;GenerateServiceReferences" Inputs="@(ServiceReference)" Outputs="%(Name)">
    <CreateItem Include="@(ServiceReferenceItemsToCache->'$(IntermediateOutputPath)Services\%(ServiceLibraryName)\%(Identity).cs')">
      <Output ItemName="Compile" TaskParameter="Include" />
    </CreateItem>
  </Target>
  <Target Name="ForceConfigFile" Condition="'$(AlreadyForcedConfigFile)' == ''">
    <Touch Files="@(AppConfigWithTargetPath)" />
    <CallTarget Targets="_CopyAppConfigFile">
      <Output ItemName="FinalAppConfigLocation" TaskParameter="TargetOutputs" />
    </CallTarget>
    <CreateProperty Value="true">
      <Output PropertyName="AlreadyForcedConfigFile" TaskParameter="Value" />
    </CreateProperty>
  </Target>
  <Target Name="BuildServiceReferences" DependsOnTargets="DoBuildServiceReferences">
  </Target>
</Project>

Honestly, I had to jump through so many hoops and pull out so many tricks while writing this that the very thought of explaining it makes me tired, so I'm just going to post it here in all its glory and if anyone's interested, they can leave a comment and I'll make an effort to explain it. You use it by including something like this in your project:

  <ItemGroup>
    <ServiceReference Include="..\WCFTest\WCFTest.csproj">
      <Project>{CD764F3F-7BA7-4E0E-B64E-A78D2C707855}</Project>
      <Name>WCFTest</Name>
      <ServiceNames>WCFTest.ChatService</ServiceNames>
      <Namespace>WCFTest,*</Namespace>
    </ServiceReference>
  </ItemGroup>

I did this by simply adding a ProjectReference to the project containing my services and then changing it to a ServiceReference item...the Project GUID is a by-product of that, and isn't actually used. ServiceNames is a semi-colon-delimited list of the service configuration entries that you want to generate proxies for, and Namespace is a semi-colon-delimited list of CLR-to-XML namespaces mappings, as described in svcutil.exe's documentation. The client configuration data will be generated in the config file that ends up being copied to your bin folder, not to the one that you edit manually...this is to prevent endpoints from piling up on top of each other, since svcutil.exe always adds new ones instead of seeing that it's creating duplicates...so if you want to see the configuration, you'll have to look in bin\Debug. The only bug I know of is that it doesn't regenerate the proxies when the service project needs rebuilding -- it does when the client's app.config file changes though, so there's a reasonable work-around (touching the app.config file) until I figure out how to tell whether the referenced project built. If I get that worked out, I'll post an update here. Meanwhile, hopefully this will be useful to someone.

May 31

Debug like it's 1899

I have been asked by a number of new programmers to recommend books for someone trying to get started. Several authors and publishers spring to mind when searching for a definitive guide on a particular aspect of software development: the Gang of Four, Charles Petzold, O'Reilly, Microsoft Press -- these are the obvious sources, prolific fonts of information with which even the most voracious programmer should be well satisfied. However, Sir Arthur Conan Doyle never seems to come up in this context, and for the life of me I can not understand why.
 
From my lofty place on page 984 (out of 1,122) of The Complete Sherlock Holmes, one thing is very clear: if Sherlock Holmes were alive today (or, you know, ever), he would quite possibly be the most formidable debugger in history.
 
Holmes once said that when one has eliminated the impossible, whatever is left must be the truth, no matter how unlikely it may seem (although interestingly enough, he never said "Elementary, my dear Watson"). He never dismisses the facts as impossible, and he never conjectures based on information he does not have. In addition to all these philosophies, he possesses an encyclopedic knowledge of his environment and the practices of his time that he employs to great effect, whether he's deducing that a suspect was recently near the scene of the crime by the colour and pattern of the mud splattered on his trouser leg or that the wife of a man he has never met had ceased to love him by the condition of his hat.
 
How often have you noticed a minor detail in how the subject of a debugging session was broken and dismissed it as random weirdness, only to realize what caused it after you've finally solved the problem? When Holmes sees a fact that he can't explain, he focuses on it and investigates it until he can, and his final solution is often based primarily on information that Watson or Lestrade had dismissed when it first came to light as a minor oddity. In fact, the more inexplicable a fact is, the more he tends to emphasize it because he sees the inexplicable parts of an investigation as the ones that set it apart from others in the past.
 
To sum up, if one were to ask Sherlock how you can learn to debug like he does, he might have this to say:
  1. Never dismiss an indisputable fact as "just plain weird"
  2. Know your domain
  3. Never underestimate the value of seemingly inconsequential details
  4. Confirm your assumptions as early and often as you can, and don't draw conclusions based on unconfirmed assumptions
  5. Read my books
 
If you ask me, you'd do well to listen to him.
View more entries
 
There are no photo albums.