Tuesday, April 7, 2009

Architects, again

It seems that I am not alone in my "Architects Rant". Here's another rant by the Secret Geek (this guy publishes some great articles, and also co-produced TimeSnapper).

A little disclaimer against rants such as this: a good architect is worth his/her weight in gold. The problem is that architects who are just "architects" tend to offer little practical value to a project. The best teams I have worked for don't have pure architects per say, they have one or more technical leads who design the system, and make the calls on refactoring, etc. And when tech leads can't unanimously decide on an approach, the project manager or delivery manager steps in and adjudicates. Works for me!

Monday, April 6, 2009

Versioning of Web Services

I was asked an interesting question the other day: how do I handle the versioning of web services? It was a hard question to answer (the person who asked me is a delivery manager of a large bank, and openly admitted that he has no real strategy as of yet either).

Incidentally, I also had struggled with another question a year or two ago, which was simply how do I handle versioning of assemblies in .Net. That gets tricky too. And as for handling of different jar versions in the Java world, well that's just a nightmare. Use Ivy I guess!

Web Services 101

This isn't a web service primer, but in simple terms, the steps consist of:
  • Whack up a wsdl (or generate one from existing classes)
  • Implement the service based on the wsdl interface
  • Publish the service in some way (UDDI, tell your friends, use twitter.com....)
  • Clients subscribe to the service via the wsdl
  • Clients produce their own client side proxies
  • Clients call web methods, and the server returns the results
To me, when you use web services in their full glory, you effectively have just another API, albeit a facade for a remote server somewhere. So, all the challenges of versioning come into play.

And Then a Change is Made

So what happens when a client wants a new feature, a different result to be returned, etc. Well, the web service implementation is updated, and perhaps so too is the wsdl (particularly if this is a breaking change).

But, what happens when the implementation of the service changes in a non-breaking way? Do we still tell the world that a new version of the web service exists? Or do we keep this secret?

When a new version of a web service is produced (for whatever reason), there are two sides to consider: client side and server sided. Yes, we need to implement the actual implementation of the new version, but the clients will require updating too.

Changing one web service client application is not too hard. But what happens when you have 100 different clients all calling the same application, and only some of them want the change?

Luckily, in the .Net world, when a web service is changed, as long as the changes do not break the contract, then clients do not require updating.

In the Java world, I have been told that the client side app will have to be recompiled based on the new wsdl (I guess Java web service implementations do a full regeneration of the wsdl, and clients always do an xsd validation against the wsdl).

An example of a breaking change is this:

Old interface:

MethodA(string arg1, string arg2, string arg3);


New interface:

MethodA(List args);

An example of a non-breaking change (in the .Net world) is:

Old interface:

BankAccount GetAccount(string id);


class BankAccount {

decimal Amount;
}

New interface:

BankAccount GetAccount(string id);

class BankAccount {

decimal Amount;
date ModifiedUTC;
}

If the client has the new version of the Bank Account class, then the date modified field will simply be null. If the server has the new version of the Bank Account class, then the date modified field will be sent across the wire to the client, but the client proxy will simply ignore the additional data within the SOAP packet.

Supporting Side-by-Side Implemetations

The good news regarding versioning is that a server can side by side support two versions of web services. However this can get messy.

I guess the golden rule here is to take a leaf out of the book of domain driven design.

Design your services as what they are... plain old objects that really don't care who or what calls them (because you might need to support many different types of interfaces, such as web services, RMI, WCF, WEP, MSMQs, you name it. You might also need to support subtly different interfaces as well, such as CorporateBankManagerService and PersonalBankManagerService (both which call the same bank manager libraries, but have slightly different workflows, API design, etc). So, if the domain is designed correctly, multiple services can be exposed (just as a thin wrapper), and also, running side by side versions isn't a nightmare either.

On the other hand, if your web service *is* your underlying service, well, doing the server side support of multiple versions is just going to get nasty. Perhaps an approach here is to actually have two separate code bases with different namespaces, etc, running side by side on the same box?

On the client side, as long as the new version of the service is there, then porting to it should not normally pose too much of an issue. The catch is that some clients may want a staggered upgrade, where some of the old is called along with some of the new... particularly when there is a chance that a rollback might be required due to an unacceptable bug, design fault, etc discovered in the live new version.

Hosting Multiple Versions of Services

So, how do we support multiple versions of a web service? I like the idea of having web services just as a thin wrapper over the real service... hopefully the underling domain model can support both the old and the new interfaces (with a bit of shoe-horning). Over time, the old version of the web service (well, interface) can be decommissioned, and an even later version can then come into the design/delivery phase.

Other options (in production today) include UDDI facilities for resolving a web service request to a particular running box - the box that serves the correct version of the web service as requested by the client. In a way this is nice... you can technically have exactly the same interfaces between the old and the new version, and the middleware running on the router/instrumentation server will proxy the request to the correct box, based on the IP address of the requesting service (for example). This could also be done through per application/machine configuration too at a guess.

And Now For Something Completely Different...

One other thought that occurred to me was to use web services just as transport mechanism. So, the only thing they publish is the fact that they have a method called "Invoke", along with maybe a parameter list which is a collection of serialised arguments, and the invoke method returns a serialised object which is unmarshalled back into an object at the client side (this is kind of how early versions of RMI worked from memory). This has advantages and disadvantages: on the good side everything is very loosely coupled. There is no concept of interfaces really, you just name a method to be invoked, perhaps a version number, and you get back some data. On the down side, you bypass all type support, schema support, discovery support, security support, etc.

For me, the idea is worth it, as I have never really found all the framework stuff related to web services of any use.

For others, maybe they do, and the idea of reducing web services to a transport mechanism just plain stupid.

Sunday, April 5, 2009

Language Extensions

Here are a few features that I would like to see built into later versions of C#/Java (actually, two of the ideas below were suggested by a friend, but I figured that I would blog them).

The "Block" Statement

Switch blocks are a very nice way of avoiding complicated nested-if structures.

For example:

Switch (currentCount)
{
case 0:
DoOneThing;
case 1:
DoAnotherThing;
case else:
throw Exception;
}

 But this can only be used in situations where the conditions equate to constants (okay, C# allows some lenience, such as supporting strings as well). But, if you need to have quite complicated evaluations of conditionals, then Switch blocks normally don't work. 

So we go into "nested-if" land:

if (GetCurrentCount() == 0)
{
DoOneThing;
}
else 
{
if (GetCurrentCount() == 1)
{
DoAnotherThing;
}
else
{
throw Exception;
}
}

This can work, but can also get messy, and is prone to bugs.

A workaround is to use some form of block mechanism, for example:

do 
{
if (currentCount == 0)
{
DoOneThing;
break;
}
if (currentCount == 1)
{
DoAnotherThing;
break;
}

// currentCount must be an illegal value
throw Exception;
}
while (false)

So, this works, but is a bit messy in terms of a redundant do-while loop (and dangerous if the loop doesn't terminate). A simple language extension could be the "block" statement, as follows:

block 
{
if (currentCount == 0)
{
DoOneThing;
break;
}
if (currentCount == 1)
{
DoAnotherThing;
break;
}

// currentCount must be an illegal value
throw Exception;
}

This simply allows you to code up those complicated logic statements that sometimes you just can't avoid/simplify/restructure. Sure, this is basically the same as a do-while loop, but makes the purpose clearer, and is slightly more efficient too (both for the compiler and the runtime). It also avoids have to use nasty nested-ifs, which can be the source of plenty of bugs. 

Pre and Post Conditions

Annotations (or Attributes in C# land) are a useful construct. In Java EE, annotations can be used on domain classes (EJBs) to specify constraints on properties. For example, you can specify that the "age" of a person must be a positive integer up to a value of 100; if this constraint is violated, an exception is raised. Here is an example taken from wikipedia (http://en.wikipedia.org/wiki/Java_annotation):



Following on from this, has anyone seen the Eiffel programming language? Eiffel is fairly funky, and is very focused on correctness of design (which I like!). The language has the concept of pre and post conditions... in other words, it has runtime checks to make sure, for example, that a reference passed in to a method is not void, that the object is in a correct state for the method to be called in the first place, and that after the method has been executed, everything is in order as well. Here is an example taken from wikipedia:



So, how about some form of merger between annotations (C#/Java) and Eiffel's pre/post conditions mechanism? This all comes down to the idea of Design by Contract, which I think is fundamentally a good one (formally specifying what the software should do, with runtime checks to guarantee these assertions). As an aside, language level assertions I feel are great as well, but typically are turned off in production, and are a fairly coarse-grained approach to enforcing design by contract.

The idea here is to have (in modern languages, such as C#/Java), some inbuilt support for pre and post conditions. The logical place for this (for me) seems to be annotations/attributes. Now, I can certainly write custom annotations, but it will require runtime support within the VM as well... any takers out there?

The New Keyword

This is a simple enhancement, just to reduce the amount of coding required on a day to day basis. 

In Java/C#, a new object is created as follows:

X myX = new X();

Why can't this be reduced to 

X myX = X();

or even

X myX();

To me, it seems like the "new" keyword in this context is redundant. 

How About Yours?

Are there any other enhancements that you would like to see in Java/C#? Let me know!

Thursday, April 2, 2009

Salary levels

Why do nearly all companies insist that individuals' salary levels must be kept confidential? This has always surprised me, as on the stock exchange (for example), the value of stocks isn't secret. Neither are the annual rich lists, which outline the top income earners (and stockpilers) for the year.

A few years back, a workmate and myself compared our salaries (well outside the work compound of course). I had put forward that we hired this guy (I was responsible for doing the interviewing and hiring of his position... to help me out on the team, which previously only comprised of, well, me really). So, we figured that I would be paid slightly more than him, but hopefully not too much more (our skill levels, experience, etc was broadly comparable). It turned out that he was getting nearly 20% more than me per year. That made both of us feel a bit uncomfortable... I was getting ripped of (it would seem), and now the person that hired him all of a sudden seemed a lot less valuable to the company. The dynamic between us changed needless to say!

The reason for the different starting salaries, as it turned out, is that we both stated what we wanted to work for. My workmate, quite rightly, named a higher starting price, but they went for that figure, no questions asked. I guess I learnt my lesson.

Here is a great article following on from this, of course once again from Joel Spolsky.