← Back to team overview

launchpad-dev team mailing list archive

Re: Want feedback on LaunchpadSharp

 

Manish,

> Launchpad provides a WADL file describing the API for the web-service. I 
> wrote a WADL->C# converter called wadlsharp[1] . Actually with minor 
> modifications it can even create VB code but that is not the current 
> target. wadlsharp is just a library and I am yet to write it's 
> documentation. I created wadlsharp just to create the C# client code so 
> that customizing the generated C# code can as easy as possible. I have 
> released v0.1 of wadlsharp. Get the code from bzr[2] or download the 
> tarball[3]

First, I'm grateful that you're taking the time to write a .NET client
for the web service. However, I think your current design will cause
trouble later on for you and your users. Let me explain.

I don't know any C#, so I don't understand what happens inside
wadlsharp, but I believe your problems start there, with the generation
of C# client code for later customization. I'm looking at
LpClientProxy.cs in lpsharp, and it looks like it's the output of
wadlsharp, or some wadlsharp-aided transformation of the WADL served by
Launchpad on a specific date.

I believe this design is a mistake, for three reasons. All three reasons
are variants on a single reason: changes to the web service are not
automatically reflected in the client. To see the changes, you must
upgrade lpsharp.

1. Let's imagine that the Launchpad web service changes in a
backwards-incompatible way. Scripts based on launchpadlib will break if
they use the feature that changed, but launchpadlib itself will still
function, and rewriting the launchpad-based script will fix the problem.
Scripts that do not use the feature will still work correctly.

>From what I can see about the way lpsharp works, lpsharp scripts that do
not use the modified feature will still work. But, lpsharp scripts that
do use the feature will break, and these scripts _cannot be fixed_
without upgrading lpsharp and _then_ rewriting the script. Because the
lpsharp code was generated from an old version of the WADL, lpsharp has
no way to find out what the new service looks like.

In real life, we take great pains not to make backwards-incompatible
changes to the web service. So this scenario is unlikely to happen. But
I can't rule it out, especially since it can happen by accident. If it
does happen by accident, your users (unlike launchpadlib users) won't be
able to use a temporary hack to get their scripts working: that would
require a new lpsharp release, and you don't want to do a new release
just to deal with a temporary problem on the server side.

2. OK, now imagine that we add a backwards-compatible improvement to the
web service. You don't really have to imagine this because we do it all
the time. Looking at the service_root_json class in LpClientProxy.cs, I
see members like:

...
private string _pillars_link;
private string _translation_import_queue_entries_collection_link;
private string _bug_trackers_collection_link;
private string _countries_collection_link;
...

For (almost) any one of these links, there was a time in the past year
when the web service did not publish that link. The same is true for
(almost) all the named operations defined in LPClientProxy.cs as
people_findPerson, etc. When we add anything new to the web service,
existing installations of launchpadlib will pick up on it. Existing
installations of lpslash will not.

This is not a catastrophe--obviously scripts written before a feature
was published will not break just because they use a lpslash that
doesn't know about that feature. But it will be annoying to your users,
and it will tie lpslash's upgrade schedule to Launchpad's.

Your users will also be effectively unable to use the bleeding-edge
'devel' version of the web service, which changes on a regular basis and
which may break its own backwards compatibility from day to day. Which
brings me to...

3. Currently there are three versions of the Launchpad web service:
"beta", "1.0" and "devel". Each publishes a slightly (or drastically)
different WADL document. This is how we're able to make the strong
promises we make about backwards compatibility (see #1).

launchpadlib's Launchpad constructor takes a version name, and reads
(from the server or from a cache) the appropriate WADL document at
startup. If there are 5 versions of the web service, there can be up to
5 cached WADL documents on the user's hard drive, but there's only one
copy of launchpadlib. Five pieces of data, one piece of code.

By contrast, LpClientProxy.cs is derived from a specific version of the
WADL as it was served on a specific date. If there are 5 versions of the
web service, there need to be 5 versions of LpClientProxy.cs in a
lpslash release. That's five similar pieces of code packaged with
lpslash, which need to be updated whenever the web service is updated
(once a month, in the limiting case).

This isn't a showstopper (unless you consider the inability to access
the new features of 'devel' a showstopper), but it violates Don't Repeat
Yourself and it'll be annoying to create and distribute these regular
releases. It will be even more annoying if you customize the generated
code, which seems to be something you're considering.

= Suggestions =

OK, what is the alternative? I suggest that you think of lpsharp not as
a C# "wrapper" for Launchpad's web service, but as a "client" or
"browser" that happens to be scriptable through C#. That's kind of
abstract, but I mean this: consider the WADL file as a piece of data to
be consumed at runtime, rather than as a template for code generation.

I appreciate that C# is a compiled language, and code generation seems
like a better alternative in a compiled language. I don't know if it's
possible to implement something like __getattr__() in C#--that's the
fundamental technology underlying launchpadlib, and nobody wants to
write launchpad['people'] or launchpad.get('people') instead of
launchpad.people.

If code generation really is the only way to make a reasonable C#
client, I suggest you generate the code at runtime, keep it cached
alongside the WADL file, and regenerate it whenever you start up lpslash
and discover that the WADL has changed. But, I don't know if that's
possible either! It might be too complicated or violate a C# security
policy.

To sum up: You will definitely be able to create a launchpadlib-like
client using the architecture you have now. But the value of an lpslash
installation will decline over time unless it's kept updated, whereas a
launchpadlib installation maintains its value over time.

Please let me know your thoughts, and feel free to ping me on IRC
(leonardr) so we can discuss this in real time.

Best,
Leonard




Follow ups

References