Friday, February 22, 2008

Are you a follower or a leader?

I'm neither. Certainly not a follower, because I'm independently-minded and naturally suspicious of authority. Nor am I a leader, because I'm not interested in shepherding my followers (and I don't expect them to agree with or obey me).

On the other hand, I almost always seem to end up setting the direction, and others usually follow my lead. Doesn't that make me a leader, and them followers? Perhaps, but then we have to restate my original question as: are you a boss or an employee?

But that was how you interpreted the question in the first place, wasn't it?

;-)

Labels: ,

Efficient singleton initialization with Interlocked

We had (are still having) an interesting discussion over at Sven-Torben Janus's blog. The discussion is about singletons, but it reminded me of a pattern I've used which has more general application. This is how it might be used to initialize a singleton:


using System.Threading;

public class Singleton
{
private Singleton() { /* ... */ }

const int NotInitialized = 0;
const int Initializing = 1;
const int Initialized = 2;
static int state;
static Singleton instance;

public static Singleton Instance
{
get
{
if (instance != null)
return instance;
while (true)
{
switch (Interlocked.CompareExchange(ref state, Initializing, NotInitialized))
{
case NotInitialized:
Interlocked.Exchange(ref instance, new Singleton());
Interlocked.Exchange(ref state, Initialized);
return instance;
case Initializing:
Thread.Sleep(0); // yield and loop until initialization is finished
break;
case Initialized:
return instance; // does this need to be interlocked?
}
}
}
}
}


This is a much cheaper pattern than the Java-style double-checked locking pattern (which doesn't work on the CLR). However, I wouldn't use it to initialize singletons, because the CLR already guarantees lazy first-time initialization for static members! Which means that all you need do is this:


public class Singleton
{
static Singleton instance = new Singleton();
public static Singleton Instance { get { return instance; } }
}


However, the pattern is still useful. I use it for service initialization, for example where I have to run a costly database query before I can start responding to service requests:


public void GuardInitialized()
{
switch (Interlocked.CompareExchange(ref state, Initializing, NotInitialized))
{
case NotInitialized:
ThreadPool.QueueUserWorkItem(this.CostlyInitializationFunction);
throw new FaultException(new ServerNotReady());
case Initializing:
throw new FaultException(new ServerNotReady());
case Initialized:
break;
}
}


As always, your mileage may vary.

Update: Some actual timing tests revealed this this wasn't so efficient after all. In fact, until I added the "if (instance != null) return instance;" check to the singleton example, it was actually slower than lock() or memory barrier techniques! With the check, it's faster, but only by 5-10%. The JITter doesn't recognized the interlocked operations as intrinsic and inline them. I suspect that the unexpectedly slow performance is due to pinning and CLR synchronization overhead. Would anyone in the know like to comment?

Further update: I exchanged a few mails with Rico Mariani, and learned that the Monitor primitive actually implements a lock-promotion protocol. Which means that unless there's actually contention for the lock, it's effectively the same thing as an InterlockedCompareExchange operation. So for all practical purposes, lock() and Interlocked.CompareExchange are equivalent. The only time you'll see a real performance difference is when you're writing code where contention is actually a significant factor. So there you go :-).

Labels: , , ,

Monday, February 18, 2008

Formatting code blocks in blogs

Trying to add nice code samples to blogs can be a bit frustrating. So I wrote a little bit of Javascript to deal with the problem. Feel free to leech (it's in the source for this page). If you make any interesting improvements, let me know!

Labels: ,

Friday, February 15, 2008

Shared APIs, part 1 of 4: The why and the how

So you're writing a three- (or more) tier application. This is probably the most common application architecture, so you're in good (or at least well-populated) company. What I'm going to advocate now is the "shared API" pattern.

Let's get the most obvious objection out of the way first. "But," you say, "surely in a service-orientated architecture we want loose coupling? Doesn't a shared API break that principle?"

The answer is yes and no. Yes, a shared API does create tighter coupling at compile time, but provided the service contract doesn't change (and it shouldn't, after a public release), you are still going to be loosely-coupled at run-time. That is to say, you don't have to update the client software every time you rebuild the service layer, and vice versa.

This is really the best of both worlds. You want tight coupling at compile time, to prevent your domain model from being (a) duplicated and hence (b) susceptible to client/server drift. Conversely, at run-time you really want the coupling to be loose, to prevent your users from getting frustrated with having to upgrade their software all the time.

There are other objections to shared APIs, but I believe that they stem principally from bad design and implementation. The basic idea of a shared API is that you have to define your service contract up-front; so arguing against it on the grounds that it makes life difficult for programmers when they want to just make a little change to the domain model or service contract is, in fact, rather perverse. After all, isn't defining your domain model first one of the most rudimentary design principles?

So now the question becomes, what does a shared-API architecture look like? I'll use WCF to illustrate. There are really two parts to a shared API: the service/data contract and the model.

Let's start with the model. You can do it the other way around, but that sometimes leads to problems later on. Step one is to create a set of interfaces (or abstract classes if you like) that represent your system:



The purpose of this exercise is to get the model right. At this point we are not considering efficiency or implementation constraints. The only concern is with the informational content of and structural relationships between the entities.

Entity relationships can be subtle things. Everybody's heard of "one-to-one", "one-to-many" and "many-to-many", but there's much more to the story. One important question to answer is that of ownership. An object may link to a set of sub-objects, but it doesn't necessarily "own" them. If a sub-object might be shared between two parents, it's almost certainly not an "owning" relationship. The other question is that of visibility. Is the child aware of its parent? (Why?) Does the parent know about its children? Answering these questions is often more of an art than a science, and volumes could be written about the different approaches that are taken.

At any rate, there are generally three types of relationship: parent contains an array of children, parent points to child(ren), and child points to parent. Each implies different ownership and visibility semantics.

Having satisfied ourselves that the domain model is correct, we now turn our attention to the use cases. Each step in a use case could potentially involve the invocation of a service or services. The question that must be answered is: "what data must be passed in which direction at this point?" This is often easy, as in the case of data that is specified to appear on a particular screen, but it can be very much more complicated - as in, what are the services required to update a form or document?

Transactions must also be considered at this point, not only in terms of the guarantees your system must make, but also in terms of the architecture you intend to use. For example, if you use MSDTC to manage your transactions, then outbound transaction flow must be enabled on all the client machines. This could be an administrative and/or security problem, in which case you might be better off changing your service model to explicitly include Begin/Commit/Rollback operations.

Once you've identified the services you require, and consolidated them as appropriate ("as simple as possible, but not simpler"), you're ready to write your service contract. There is generally an intersection between your domain model and your service contract. Try not to focus too much on this! Remember that the service model is a completely different thing from the domain model. Services operate in a specific context, whereas domain entities are abstract and generalized.

Here's an example of a service contract for the domain I described above:



Next time I'll talk about the implementation aspects of shared APIs as they relate to their client and server consumers, and also about the limitations of object orientated languages in this respect. Those familiar with WCF will probably have noticed some problems with the code above, and can therefore anticipate what is coming...

Labels: , , , ,

Slicing objects; or, when you only want to pass the piece the method wants

I humbly refer you to this post by Sven-Torben Janus, and add only the following helpful hint: System.Runtime.Serialization.FormatterServices.GetUninitializedObject().

Labels: , ,