«
February 2003
»
Ping WebLogs.com using XML-RPC.NET
Monday 24 February
I came across some sample XML-RPC.NET code by Scott Watermasysk today. The article describes how to ping Weblogs.com. As I read it I thought it might be worth re-implementing the sample using an interface because I believe this is now the best way of using XML-RPC.NET on the client-side. Also it would be opportunity to illustrate a few more features of the library.
The API for ping WebLogs.com is described here. There is a single method called ping which takes two parameters, the name of the weblog and its url. The method returns a struct containing a boolean as to whether an error occurred and a string containing an error message if an error did occur. So the first steps are to define a struct to represent the return value and an interface to represent the XML-RPC method:
using System;
using CookComputing.XmlRpc;
[XmlRpcMissingMapping(MappingAction.Ignore)]
struct PingResult
{
public XmlRpcBoolean flerror;
public string message;
}
[XmlRpcUrl("http://rpc.weblogs.com/RPC2")]
interface IWebLogs
{
[XmlRpcMethod("weblogUpdates.ping")]
PingResult Ping(string weblog, string url);
}
This code encapsulates the interface to the XML-RPC endpoint. Once defined it can be re-used elsewhere if required. The XmlRpcMissingMapping attribute is used to specify that all the members of the struct are optional (this being XML-RPC you can never be quite sure what a server is going to return). Also, flerror is specified as type XmlRpcBoolean: if we had used bool we would not know whether the server had actually returned this member in the struct. The member would contain a default value of false if it had not been returned. By using XmlRpcBoolean we can check whether the server returned the member by testing whether the member is null, because it can either be true or false if a value was returned or a null reference if it was not.
Scott's example wraps the WebLogs.com call with some extra functionality but before implementing that its worth demonstrating how a proxy can be generated from the interface and used to make calls. Although the proxy code could be written by hand, in most cases it is easier and less error-prone to generate the proxy code programmatically using the XmlRpcProxyGen class in a single line of code as the following example illustrates:
IWebLogs proxy = (IWebLogs)XmlRpcProxyGen.Create(typeof(IWeblogs));
PingResult result = proxy.Ping("My Fictitious Blog", "http://www.fictitiousblog.com");
Console.WriteLine("{0} {1}", result.flerror, result.message);
Returning to Scott's sample, his class which wraps the XML-RPC call can be implemented as:
public class WeblogsNotification
{
private string errormessage = "No Error";
public string ErrorMessage
{
get{return errormessage;}
}
public bool Ping(string name, string url)
{
bool result = false;
try
{
IWebLogs proxy = (IWebLogs)XmlRpcProxyGen.Create(typeof(IWebLogs));
PingResult response = proxy.Ping(
"My Fictitious Blog",
"http://www.fictitiousblog.com");
if (response.flerror == null || response.flerror == false)
result = true;
else
{
if (response.message != null)
errormessage = response.message;
else
errormessage = "Unknown Error";
}
}
catch (XmlRpcFaultException fex)
{
errormessage = fex.FaultString;
}
catch (Exception ex)
{
errormessage = ex.Message;
}
return result;
}
}
There are a couple of points worth mentioning here. First, because the members of the return struct were specified as optional (using the XmlRpcMissingMapping attribute on the definition of the struct) and are both nullable types, we can test them for being null to determine whether they were actually returned by the server in the struct. Second, we handle the case where the server returned an XML-RPC Fault response by catching XmlRpcFaultException separately.
Finally an instance of the class can be used to make the ping:
class Class1
{
static void Main(string[] args)
{
WeblogsNotification wn = new WeblogsNotification();
if(wn.Ping("My Fictitious Blog", "http://www.fictitiousblog.com"))
{
Console.WriteLine( "Weblogs was notified and accepted");
}
else
{
Console.WriteLine( wn.ErrorMessage);
}
}
}
A couple of final points: for an XML-RPC endpoint such as WebLogs.com there isn't a big advantage to encapsulating its methods in an interface but you'll find that if you need to make calls to endpoints with multiple methods, with possibly more complicated parameters and return values, using interfaces does result in more understandable and reusable code.; also, the use of the XmlRpcProxyGen class does avoid errors which can slip in when proxies are hand-coded.
Problem with XML-RPC.NET 0.8.0
Monday 24 February
I've just noticed a problem with the nullable types XmlRpcInt, XmlRpcBoolean, and XmlRpcDateTime. I'll issue a fix within the next hour or so.
UPDATE: 0.8.1 is now available. I've done some quick testing on this and it fixes the known problems, but I need to write some comprehensive unit tests for the nullable types before I have full confidence in this area.
XrpGen
Monday 24 February
Joe Bork has released his XrpGen tool. This is based on his XmlRpcProxyCodeGen class I mentioned recently. It takes a source file containing an interface and generates the source for the corresponding XML-RPC proxy. His post has all the details.
The custom build steps feature of Visual Studio 2003 will allow XrpGen to be used in a pre-build step to generate proxy code which is then used in the build. This will ensure that the proxy code is always up-to-date with the interface.
XML-RPC.NET 0.8.0
Monday 24 February
I released version 0.8.0 of XML-RPC.NET last night. It contains support for optional struct members but the FAQ documentation is not updated in this release. However this blog entry shows how optional members are used in practice.
Note that new nullable types such as XmlRpcInt can be used where a struct returns optional value types such as integer. Otherwise you would not be able to determine whether the member had not been set or was set to its default value. Similarly when passing a struct in a call, the nullable types enable you to specify whether a member should be included in the XML-RPC struct in the request.
The release also includes some interfaces for the following APIs:
- Blogger
- MetaWeblog
- Movable Type extensions
- Meerkat
The interfaces are work in progress but I've been using all of them except the Movable Type extensions in clients.
Webloging API Blues
Sunday 23 February
I've been spending some time recently trying to develop .NET interfaces to represent the various blogging APIs. These interfaces can then be used with XML-RPC.NET to implement blogging clients. I've tried to make the APIs as generic as possible but this has proved to be difficult, not least determining what the APIs actually support. To iterate a point I made a few days ago, why does nearly everything concerned with XML-RPC have to be so vaguely specified?
I thought the Blogger API would be fairly straightforward but some key methods - deletePost and getRecentPosts - are not mentioned in the Blogger API spec. Also, its not clear what the types of items such as postid and userid are. These can be either strings or integers depending on the server (I've been testing with Movable Type, EraBlog, and Radio).
The MetaWeblog API is worse. The spec is a typical Dave Winer stream of consciousness effort and the only effective way to determine what various servers support is through trial and error with ProxyTrace.
As far as XML-RPC.NET is concerned, there is the problem that if a separate interface is used for each API, say IBlogger and IMetaWeblog, then its not possible to generate a proxy automatically using the XmlRpcProxyGen class (it can only generate a proxy derived from a single interface). This wouldn't be a problem if the two APIs were self-contained but MetaWeblog doesn't have a deletePost method (and getRecentPosts is missing in the Radio implementation). So until I enhance code generation to handle derivation from multiple proxies, it will be necessary to create two proxies, one for each interface.
By the way, I've written this entry, and the previous, using a blogging client I've written as part of the above investigation. I don't know if I'll ever polish it up enough for public release but it certainly beats using the web interface to Movable Type.
Mildly Irritating Bloggers
Sunday 23 February
Jeremy Zawodny lists The 10 Habits of Highly Annoying Bloggers. I'm not so fussy as him: there are only two things that mildy irritate me in blogs.
First, the habit that some bloggers have of linking some words to their dictionary definition at Dictionary.com. This gives the impression that the blogger either thinks he/she is more intelligent than the readers or the readers are stupid. Either way, it is irritatingly patronising.
Second, newly born baby pictures. Although our own babies are the most wonderful things we can imagine, I don't think we feel the same about others. I'd much rather see a picture of someone's pet dog!
CodeDOM and XML-RPC Proxies
Tuesday 18 February
Joe Bork is doing some cool work with the .NET CodeDOM. He has implemented some code to generate a CodeDOM representation of an XML-RPC.NET proxy based on an interface definition. This is then used to output source code for the proxy in whichever language you want (assuming the language supports CodeDOM). For example, given the following interface:
interface IHello
{
[XmlRpcMethod]
string Hello(string name);
}
Joe's XmlRpcProxyCodeGen class currently generates this C# proxy:
namespace HelloRpcProxy
{
public sealed class HelloRpcProxy :
CookComputing.XmlRpc.XmlRpcClientProtocol, IHello
{
public HelloRpcProxy()
{
}
[CookComputing.XmlRpc.XmlRpcMethodAttribute("Hello")]
public string Hello(string param_0)
{
object tempVal = null;
string retVal;
object[] tempArr = new object[] {param_0};
tempVal = this.Invoke("Hello", tempArr);
retVal = ((string)(tempVal));
return retVal;
}
}
}
Question 2.16 in the XML-RPC.NET FAQ is currently unanswered:
How do I implement a client in JScript.NET?
I've put off answering this because I know hardly anything about JScript.NET. But now I can include something based on this output from XmlRpcProxyCodeGen:
package HelloRpcProxy
{
public final class HelloRpcProxy
extends CookComputing.XmlRpc.XmlRpcClientProtocol
implements IHello
{
public function HelloRpcProxy()
{
}
public final CookComputing.XmlRpc.XmlRpcMethodAttribute("Hello")
function Hello(param_0 : System.String) : System.String
{
var tempVal : System.Object = null;
var retVal : System.String;
var tempArr : System.Object[] = [param_0];
tempVal = this.Invoke("Hello", tempArr);
retVal = System.String(tempVal);
return retVal;
}
}
}
This will be a useful addition to the XML-RPC.NET library.
XML-RPC and WSDL
Monday 17 February
Oren Novotny posted an interesting question to the XMLRPCNET Yahoo group today:
Is there any way to create a tool similar to WSDL.exe that will query an XML-RPC service and then generate the required interfaces and structs? Does the XML-RPC spec have any way of returning that information?
While it's very nice that only an interface definition is currently required as opposed to creating the classes, it is the structs that a real pain. Many times a method will use a struct that has 15-20 members, with some of those being other structs with a similarly large number of members. It would be really, really nice if those could be auto-generated.
I replied:
I agree it would be very useful to have a wsdl.exe-like tool for XML-RPC. This would only be possible if XML-RPC servers returned a standard high-fidelity description of their services.
The only existing "standard" is the Introspection API, which is worthless from this point of view. I was involved in discussion with some members of the XML-RPC Yahoo group a long time ago about defining something more useful but that fizzled out. Another effort was Dave Winer's ALIDL which had about as much potential value as the Introspection API.
However I see no reason why an XML-RPC binding could not be defined for WSDL. The use of the XSD would allow accurate description of the types in XML-RPC requests and responses. The main problem with WSDL from an XML-RPC perspective is that it might seem over-complicated by XML-RPC standards.
But assuming you can extract the type information from your server code, which would be the case with something like XML-RPC.NET which is written in a statically typed language, the WSDL could be generated automatically by the server and then consumed automatically on the client side by the wsdl.exe-like tool, so there would be no need for manual handling of WSDL.
It could be an interesting project Broadly the work would involve tasks such as:
- defining the XML-RPC WSDL binding
- implementing the code to generate WSDL on the server using reflection
- implementing code to dynamically build an interface which could then be fed into the XmlRpcProxyGen.CreateAssembly method (which outputs an assembly to disk)
- extending other implementations of XML-RPC in the same way (or persuading their implementors to do the same)
As I hinted earlier the use of something like WSDL does go slightly against the spirit of XML-RPC. However as Oren suggested, once your requests and responses contain complicated types, the dynamic free-form nature of the protocol becomes a hindrance. Although the public XML-RPC APIs tend to be fairly simple, I've seen some of the types that companies are passing around in their internal XML-RPC-based applications and they can be very complicated. I can't see why the two approaches couldn't co-exist: use of WSDL or something similar for complex requirements would not in any way affect the more dynamic uses of XML-RPC.
I think the last point is important. If XML-RPC is a viable alternative to SOAP then people will want to use it in complicated ways and when you start doing that you need some way of specifying and verifying what a server implements. The very informal API specs that XML-RPC seems to attract are often wrong, or misunderstood so that the server implement something different. Businesses are using XML-RPC for serious purposes and this potential for confusion wastes time and money.
XML-RPC Blogging APIs
Sunday 16 February
I've come down with a cold this weekend and didn't get much done. I managed to do some testing of some sample interface definitions I'm working on for inclusion in the XML-RPC.NET FAQ. The interfaces are for the Blogger and MetaWeblog APIs, and will make writing .NET blogging clients easier. For example, assuming you've included the assembly containing the CookComputing.Blogger assembly, you just need to create a proxy via the code-generating XmlRpcProxyGen class, set the required url, and then make any of the Blogger API calls on the interface. For example, to retrieve the list of categories available for a blog:
using CookComputing.Blogger;
IBlogger proxy = (IBlogger)XmlRpcProxyGen.Create(typeof(IBlogger));
XmlRpcClientProtocol xpc = (XmlRpcClientProtocol)proxy;
xpc.Url = "http://EraBlog.NET/rpc/v1.1/erablog.xmlrpc";
Blogger.Category[] categories
= proxy.getCategories("1234", "MyBlog", "pwd");
The interface can also be used to implement the server side of these APIs. In this case you derive the service class from the XmlRpcService class and the required interface(s), and then implement the interface methods in this derived class.
While testing a Movable Type server I noticed that the XML-RPC fault response is incorrectly implemented:
<?xml version="1.0" encoding="UTF-8"?>
<methodResponse>
<fault>
<value>
<struct>
<member>
<name>faultString</name>
<value><string>Invalid login</string></value>
</member>
<member>
<name>faultCode</name>
<value><string>Server</string></value>
</member>
</struct>
</value>
</fault>
</methodResponse>
Of course, the fault code should be an integer type. I was pleased to note that the parse stack feature I recently implemented in the deserializer worked successfully:
"fault response contains string value where integer expected [fault response : struct mapped to type Fault : member faultCode mapped to type Int32]"
Fault is the .NET type which the fault response is mapped onto:
struct Fault
{
public int faultCode;
public string faultString;
}
This is a simple example but in general the parse stack allows diagnostics to be produced for nested types within structs and arrays. Having seem some of the very complex responses handled by some users of the library, this can be very helpful where the XML-RPC - .NET mapping of types is incorrect, for example where the response is different to what was documented.
Named Pipes Channel
Friday 14 February
Commenting on my recent post about the TCP channel, Duncan Smart suggested a look at Jonathan Hawkins' Named Pipes Channel sample. I've not had a chance to investigate it yet but the use of named pipes sounds promising from a security point of view, at least in the scenario I'm interested in where a server application consists of multiple processes on the same machine. The Named Pipes channel could be extended to restrict access to the pipe(s) to specified accounts and so make the use of Remoting secure.
Smart Clients Not So Smart?
Thursday 13 February
I've not been following the .NET smart client saga very closely but if the Microsoft TaskVision sample (via Chris Sells) is state-of-the-art it suggests that the original vision has been watered down somewhat. I say this because I went to run the client but stopped when I noticed this requires downloading and installing an MSI package. I really liked the concept of being able to run clients, from a URL, in a "sandbox" which uses Isolated Storage on the client machine to persist data without having general access to the file system.
Running an msi package supplied by the producer of a client breaks security. Ideally, when clicking on a link to run a true smart client, I'd like to be presented with a dialog telling me which permissions the smart client is asking for and giving me the opportunity to choose whether I accept them, or even accept a subset if the client offers this alternative.
Another feature of the hypothetical zero-install client is that it doesn't involve that horrible feeling I always have when I install software on my system, that it will either conflict with something already installed or I'll never be able to uninstall it without breaking something, or worse still that I end up in MSI hell in which every time I run the client it fires up the MSI installer to fix some part of the installation, only to fail because the version of the software installation package on the corporate network has changed.
TcpChannel Impressions
Wednesday 12 February
I've been investigating partitioning a server application into separate processes so that verifiable .NET code can run in a separate environment where it can't be affected by unsafe C++, both managed and unmanaged. I was very surprised to see how poor the performance of Remoting via the TCP channel is compared to DCOM. Calling a simple method which takes a small string as its single parameter and returns another small string, TCP channel Remoting can only achieve about 1000 calls per second whereas DCOM was achieving about 9000 calls per second on the same machine.
The lower performance may be acceptable in the context I'm investigating but the lack of built-in authentication and authorization is more worrying. MSDN suggests:
If you have a choice between using the HttpChannel and the TcpChannel, it is recommended that you use the HttpChannel and host your remote objects in Internet Information Services (IIS), no matter what the user authentication and authorization models are. IIS hosting provides support for wire-level protection using Secure Sockets Layer (SSL) and authentication using Integrated Windows Authentication (formerly NTLM authentication) or Kerberos.
The TcpChannel, as an implementation of the Transmission Control Protocol (TCP), does not have default support for some of the robust authentication standards that the HTTP standard does. Within a secured environment (one that has wire-level protection such as IPSec), the high-speed TcpChannel can be used, but it is not recommended over the Internet or a nonsecure intranet.
Rearchitecting the server to run in IIS is not an option and the environment won't necessarily be secure, so using the TCP channel secure would require custom encryption sinks as described in Ingo Rammer's excellent Advanced .NET Remoting. However, do-it-yourself security is always a risky business and I'd much prefer it to be available as part of the framework. DCOM security can be a hassle but it does exist. Why wasn't similar functionality provided with Remoting?
Timing of .NET Patent
Tuesday 11 February
Clay Mayers posted this on the win_tech_off_topic list:
Another reason the patent maybe ruled as invalid is that Microsoft has a tendency to spread FUD before introducing a technology. This is in effect selling the patented product testing the waters to see if people will buy. Once you do that, you only have a year to file the patent. After that, your own product becomes prior art for your patent. This one was filed Feb of 2002 so they had better not have made any promises about what the system will do prior to Feb of 2001.
This puzzles me. I was at the PDC in 2000 when .NET was announced and described in some detail in the various sessions. Surely, as Clay suggests, this public description of the technologies, including printed handouts, invalidates any claim made a year and a half later?
.NET Patents
Tuesday 11 February
Its no surprise that Microsoft has been filing patent applications to protect .NET (CNET report). Now the issue is coming into the open it really does make you wonder as to what they intend to do about other implementations of .NET, such as Mono, which are covering the whole of .NET, not just the stuff in the ECMA specification.
I've just had a look at the libraries specified by the ECMA standard (available here) and although there is obviously a lot missing compared to Microsoft's .NET framework, there might be enough in it as a base class library. I don't necessarily believe that everything in Microsoft .NET should be replicated - it would be nice to see .NET open source projects breaking new ground instead of slavishly copying Microsoft - but obviously it would be bad if a load of basic library functionality had to be reproduced. From a quick look at the specified libraries its not clear to what degree this is the case. For example, the XML DOM classes seem to be missing although the XmlReader/Writer classes are there. That's a big omission but the XML DOM might be covered by W3C standards for all I know.
From a personal point of view its clear that XML-RPC.NET uses classes which are not in the ECMA standard, so I have a practical interest in knowing what the patent position is. I'd like the library to run on non-Microsoft platforms which may be restricted to the ECMA-compliant base classes. Of course other library classes which do not copy .NET but have similar functionality mght be available on these platforms, but that spoils the usefulness of a framework which is guaranteed to be available everywhere. Maybe I should factor out the functionality required for working with ASP.NET and .NET Remoting and ensure the remainder is ECMA compliant.
The patent application itself is completely confusing to my untrained eye, so broad as to be seemingly meaningless. No doubt there will be some useful analysis over the next few days to clarify this.
Functional Objects Dylan
Tuesday 11 February
Ted Leung's blog entry about the programming langauge Dylan (via Chris Double) prompted me to look at the Functional Objects site. Dylan has only been vaguely lodged in my mind as an "infix version of Lisp" and a language/development environment that was canned by Apple a few years ago, so it was interesting to read a bit more about it. The article Beyond Java?, which compares Dylan with Java, is worth reading because the comparisons also work with C#. Dylan has features such as MI, multi-dispatch, no casting, and macros which are all missing from both Java and C# (the macros being real macros in the Lisp sense and not C-style macros).
I get the impression that Dylan is a considerably richer language than Java or C# yet is claimed to be just as efficient as those languages. From my experiences with Lisp and Scheme I think the prefix style with lots of brackets is always going to put off a majority of developers so maybe something like Dylan with its more conventional-looking syntax could have been a success. Paul Potts certainly thinks so in his Apple Dylan Eulogy:
Dylan was, in part, an attempt to build a bridge between static language users and the dynamic language community. The Cambridge team wisely understood that C programmers would be generally unwilling to convert to a parenthesized, prefix syntax: for this reason, Dylan was given a Pascal-like syntax. Programmers who have used Lisp generally come to feel comfortable with it; I've used Scheme enough now to feel be somewhat accustomed to the style, but I will probably always prefer a non-Lispy syntax. Computer science types can say "that's just syntax; it is irrelevant," but in fact many barriers to language adoption are cultural and practical, not technical.
It seems to be possible, to this day, to graduate from a computer science program having learned either the idioms and scenery of the Lisp/Scheme world, or the rules and scenery or the C/C++/Java/C# world, but not both. We just generally aren't willing to venture into each other's alien landscape. The static language community continues to make marginal improvements to its languages, not realizing the improvements they are discovering are they are discovering are twenty or more years old. But that is the subject for some ranting another day.
This is certainly true if you have not studied Computer Science, in which case you have probably only learnt languages such as C++, Java, or even only VB, and may have developed a fairly blinkered view of programming languages in general. I know this applies to me and which is why Im finding languages such as Lisp and Scheme so fascinating. To take a simple example, if youve only worked with C++ or Java you may not be aware that the single dispatch mechanism of these languages is a subset of the multiple-dispatch mechanism that some other languages have.
Its difficult to say for sure whether being familiar with a wider range of languages actually helps you design and implement better Java or C# programs. My feeling is that being more aware of the limitations of these languages does help: seeing things from a broader perspective improves understanding and in the same way that Patterns enhance the way you think about design problems, knowledge of a wider range of languages gives you more concepts to work with, even if you cannot directly use some of the techniques with the language you are working with.
DCOM String Binding Problem Explained
Friday 7 February
I posted a few weeks ago about a DCOM string binding problem with Windows 2000. The root cause of the problem was that from Windows 2000 onwards the list of string bindings returned by a DCOM server have a fully qualified domain name as the first entry:
0x7 reeves.shooting.com 0x7 64.124.140.181 0x7 192.168.7.12
It turns out that that there is no way round this. I posted to one of the MSDN managed newsgroups yesterday and Santhosh Pillai helpfully replied:
There is no way you can avoid getting FQDN in the marshaled interface pointer. The FQDN present in the marshaled interface pointer is a huge help when DCOM server is behind a NAT-based firewall.
You may, however, add a host file (system32\drivers\etc\hosts) entry in*every client* box which points reeves.priv.com to the correct IP address.
Interesting. Although the solution he suggests is not really suitable for our situation, its useful to know where we stand.
This sort of problem has been very frustrating when working with DCOM. Fortunately there has been a huge paradigm shift in .NET where everything is configurable and even replaceable, for example you can install and configure your own Remoting channels. The string binding problem will cause extra work for us because DCOM is a black box and we can't configure away the problem. The .NET paradigm of openness is very welcome.
Poor Obfuscation Implementation
Thursday 6 February
Andy Oliver, with Avik Sengupta, has written an article on Opening Microsoft File Formats to Java. Its the first article in a three-parter describing the POI project which is implementing Java code to access Microsoft Structured Storage files and the file formats that use Structured Storage, such as Excel and Word documents. What does POI stand for? According to the POI site:
POI stands for Poor Obfuscation Implementation. Why would we name our project such a derogatory name? Well, Microsoft's OLE 2 Compound Document Format is a poorly conceived thing. It is essentially an archive structured much like the old DOS FAT filesystem. Redmond chose, instead of using tar, gzip, zip or arc, to invent their own archive format that does not provide any standard encryption or compression, is not very appendable and is prone to fragmentation.
I've toyed with .NET code accessing structured storage but I only got as far as implementing a Managed C++ wrapper for the relevant COM APIs. An implementation written purely in C# would have the advantage of being verifiable and so could be used in, say, Internet zone security senarios. Even so, in that situation you'd have to use Isolated Storage which provides its own hierachical directory/file structure anyway (I wonder if Isolated Storage is built on top of Structured Storage?). Another use would be accessing Structured Storage files on a Linux system with Mono. I can think of an application fairly close to home where that could be useful (which reminds me, don't ever think of using Structured Storage via remoted COM interfaces).
Maybe someone is already porting POI to .NET - it seems very popular to port Java APIs - but I'm not sure I would want to do it.
VS.NET 2003 C++ Enhancements
Wednesday 5 February
Richard Grimes has a worthwhile article in MSDN magazine about some of the new C++ features in VS.NET 2003(via Sam Gentile).
Its interesting to note that the compiler now allows you to generate verifiable assemblies, but by the time you have taken into account all the restrictions on the C++ code - for example you cannot use __nogc types - you are essentially left with a C++ "skin" for C# rather than C++ in all its power and glory. I was slightly puzzled by the claim that you can use platform invoke: surely this would prevent an assembly being verifiable?
Although I've never felt that MC++ should have much of a long-term future - we must get away (for most purposes) from developing in languages which are not type-safe and which do not have garbage collection - its great for making the transition to a managed environment. For example, I've been experimenting with using NUnit to test unmanaged library code. The unit tests are implemented in test fixtures implemented as__gc classes with MC++. The unmanaged code is simply linked to the test assembly and, as they say, It Just Works. The assembly can then be run in NUnit which extracts details of the tests to be run via reflecting on the attributed C++ test code:
using namespace System;
using namespace NUnit::Framework;
namespace LibTest
{
[TestFixture]
public __gc class TestTypeLibCache
{
public:
[Test]
void ServiceLocatorMethods();
};
};
Steve Waring's Smalltalk Journal
Monday 3 February
My recent entry on continuations led to Steve Waring's Smalltalk Journal via Chris Double. Steve has an interesting piece on his implementation of SWScheme which is written in Dolphin Smalltalk.
Although I've never used the language, Smalltalk was my first introduction to object-oriented programming because of the August 1981 Smalltalk-focused issue of Byte. It was heady stuff, not least because of the GUI-based development environment. The article Design Principles Behind Smalltalk from that issue is well worth reading.
Sunday Morning
Sunday 2 February
I'm finishing off some changes to the documentation generator in XML-RPC.NET. These include some fixes and also code to handle optional members. The final step before releasing 0.8.0 is to update the FAQ.
Writing test code containing C# struct definitions I keep slipping back into C++ mode, forgetting that C# struct members are not public by default. This is irritating because the serialization code in XML-RPC.NET requires struct members to be public (this allows the code to work in Internet zone security type scenarios, e.g. for a smart client).
I can't think of anything else where I make mistakes in C#: it a very easy language to write code in. After writing a lot of C#, returning to C++ make me realize how unproductive C++ is. I wonder how many people are doing greenfield development in C++ these days?
Testing the documentation generator in XML-RPC.NET again emphasises how important it is to design for testability. I've modified the code slightly to expose the generator so that I can write a test harness which generates a html file containing the documentation for as many interfaces/classes as I want to define. The problem is that I can only inspect this manually to check the output. I should have designed the code so that much of the functionality could have been tested in NUnit. A manual inspection would still be necessary to check the presentation of the data but not to check the data itself.
I guess I need to do some refactoring. There is also duplicated code in several places which could do with some reorganization and the structure of the code in some places reflects the piecemeal development over a long period. I'm a bit wary of doing this until I've made the unit tests much more comprehensive. I've not used any of the available refactoring tools, for example C# Refractory. This provides several common refactorings such as:
- Extract Method
- Extract Superclass
- Extract Interface
- Copy Class
- Push Up Members
- Rename Type
- Rename Member
- Rename Parameter
- Rename Local Variable
I need to do some research as to whether tools like this make a difference compared to editing the code by hand.