Friday, May 25, 2007

FePy r6 + 1 line of code runs PyFit

Following up this trail again --

IPCE-r6 doesn't run PyFit out of the box, but it gets a lot closer than the mainline does:

Traceback (most recent call last):
 File C:\PyFIT-0.8a1\fit\FitServer.py, line 7, in Initialize
 File , line 0, in __import__##4
File C:\PyFIT-0.8a1\fit\fitnesse\FitServerImplementation.py, line 49, in Initialize File , line 0, in __import__##4 File C:\PyFIT-0.8a1\fit\fit\Fixture.py, line 21, in Initialize File , line 0, in __import__##4 File C:\PyFIT-0.8a1\fit\fit\TypeAdapter.py, line 34, in Initialize File , line 0, in __import__##4
File C:\PyFIT-0.8a1\fit\fit\taBase.py, line 36, in Initialize File C:\PyFIT-0.8a1\fit\fit\taBase.py, line 82, in TypeAdapter AttributeError: 'module' object has no attribute 'ast'

This line is the first to look for compiler.ast members to initialise data members. Looking at the IPCE bundle, C:\IPCE-r6\Lib\compiler\ast.py exists and has the values required.  It's just that its __init__.py is empty. , so we can patch C:\IPCE-r6\Lib\compiler\__init__.py to be

import ast

and it all works, without having to touch PyFit code at all.

This is the "no change to client code" equivalent to decorating PyFit with a suitably guarded explicit load

import fepy
fepy.install_option('ast')

The behaviour is not a bug, but a feature as FePy by default does not load code that is rarely used, so as to speed start-up.

Note

We still don't have parsing of lists, tuples, dictionaries or complex numbers as arguments, since we still don't have the transformer.parse method to expose as compiler.parse; the unit tests in TypeAdapterTest.py report

Ran 117 tests in 2.468s

FAILED (failures=3, errors=5)

However real tests that don't have these non-scalar types do run happily on FePy-r6.

Tuesday, May 22, 2007

C++/CLI

Notes on mixed types -- the invaluable gcroot<T> template.

Mixing Native and Managed Types in C++ -- plus AutoPtr generic

AutoPtr revisited.

Silverlight -- more than just Flash

A lot -- almost all -- the talk about the new Silverlight technology from Microsoft has been about the "shiny", the ability to place hevyweight UI in the browser, and whether or not it will succeed in displacing Flash in a way that Java applets never managed to (But see also here).

Somewhat lost in all this has been what the technology is, especially in the 1.1 release, currently in alpha.  Of course this isn't new -- remember all the "What is .Net?" thrashing about that took place when that technology was first announced -- all talk of web services and "Hailstorm" (MSFT Passport-on-steroids) -- and what we understand by the term now over 5 years down the line

The basis of the sliverlight technology is a portable version of the CLR (.Net) framework, referred to as the Core CLR.  This is the bytecode engine and a slightly cut down set of APIs, though cut down in different ways to the .Net Compact framework -- it relies on APIs not present in that version.

And then comes the good bit.

Layered on top of the CLR is the new DLR (Dynamic Language Runtime), which abstracts the flexible duck-typing behaviour seen in JavaScript, Ruby and Python -- and these (along with the inevitable VB) are the target languages for the DLR support in coming releases. Python and JavaScript (EcmaScript 3.0) are in the 1.1 alpha, with the others to follow.  More... Yet more...

The DLR has also appeared in the refactoring of IronPython -- and the recent 2.0 alpha release includes the Microsoft.Scripting.dll that is at the heart of the DLR (though the current transition state is made apparent by there being a Microsoft.Scripting.Vestigial.dll representing the remains of a first cut at refactoring to separate out what is now the DLR).

Two blog posts from one of the DLR developers (who's also been involved in Jython as well as IronPython) on how dynamic objects are being modelled in the CLR

and the start of a series on how compilation is handled (DLR Trees, part 1), which shows how it is complementing the LINQ features of C# 3

With IronPython and, soon, IronRuby as first class languages for the .Net framework there seems to be some hope that the .Net == C# (or, for those who want to join a sort of Coke vs Pepsi style debate, .Net == C# or VB) status quo may actually be coming to an end.

MSBuild -- build from solutions without DevStudio

This is a tool that had passed me by until I spotted a passing reference to it just the other day. Buried in your C:\WINDOWS\Microsoft.NET\Framework\v2.0.50727 folder is an executable called MSBuild, which will take .*proj and .sln files and build them.

It consumes XML files in a format of which the .*proj files are a special case; and handles solutions (.sln files)  as a special case.  While I've not had chance to explore the ramifications of the XML build format, this appears to be Microsoft's own preferred build system and one that will bear investigation and adoption, especially for those projects (like Callisto) which use DevStudio for developer builds and thus have had it  installed on their build machines, when they could have gotten by with just the .Net 2.0 Framework.

MSBuild with solutions -- how to capture the temporary script file generated from a solution; and how to actually build just one project from a solution

MSBuild with ASP.Net -- Visual Studio 2005 no longer uses project files for ASP.NET; this is how to roll your own from the solution.

Solution files and MSBuild -- Automated hoisting of project build from the solution file.

These latter look like something that could be ported into an IronPython script with ease.

…and caught up. Phew!

Interviewing

Now I've just finished a round of interviewing, time to let out some of the secrets. It's really about whether the candidate can think on their feet (and can work elegantly around places where they aren't familiar with detail) and knows general software engineering techniques in some depth (according to their length of experience).

Five essential phone-screen questions -- not bad at all

Job Interview 2.0, now with extra riddles -- Is moving Mt Fuji really the way you want to go?  Or does it just select for those with an eye to making the solutions more complicated? Me? I'd not work for a company that uses this interview style. The 10/5/2/1 minute problem I know the answer is 1 minute faster than the obvious one using the 1-minute runner, and if I wanted to do it again, I'd write a program to solve it.

"My favorite interview question" -- it's "How might you design a program that lets people play Monopoly with each other over the internet?"  Not a question that I personally have tried, but the post analyses what makes this question a good one.
 

Learning Ruby

HacketyHack -- whytheluckystiff has now launched a "Ruby for kids" site to complement

why's [poignant] Guide to Ruby -- the original mind-expanding course; or for more staid heads

The Pickaxe Book -- 1st edition, on line

OK, so only the first one is news -- and something we've needed for years, since the old days of hands-on Basic on a PC are long past.

Links for 22-May

Hard-core concurrency considerations

JavaScript -- Lisp in 'C's clothing -- used to demonstrate the Y combinator

HTML5 now accepted for review

You think you know JavaScript but you have no idea -- excellent presentations

The high cost of free tools

An Introduction to Ranges (JavaScript/DOM)

Is HTML5 a slippery slope?

Zoomable UIs

Design Patterns Aren't

"Maybe" in Java

Process is about people

Managed Code Custom Actions : no support on the way and here's why --why we still need to do installer custom actions the hard way

Apple's new Invisble UI

Another look at HTML5

Modularity, Ruby and doing the right thing -- cross language behaviour in Silverlight/DLR

C# and the compilation tax -- " Over the last four years, I've basically given up on the idea that .NET is a multiple language runtime."  I know how he feels.

Web 2.0 is neglecting good design -- BBC News picks up on Jakob Nielsen's comments

Design by Grid -- grid layout in the post <table> age

A nostalgic look at using XMLHttpRequest with SOAP -- how to call a web service from your browser the "old-fashioned" way (i.e. how to write the code that ASP.NET AJAX does for you).

Silverlight at the command line -- Test your Silverlight applications in the real thing in scripts (the Silverlight engine is highly sandboxed, so it's going to be limited as an application context)

Silverlight : dynamic languages in the browser -- roundup article

Ruby on Rails on TDD -- a 15-step guide to test-driven web apps

JavaScript Libraries : the big picture -- high level, high speed. Also, good stuff in the comments.

Breaking out of the box -- Learn the rules and then break them for grid-based page designs.

LessMSI -- MSI unarchiver 

Hackers and Fighters -- or, Theory vs. Practice 

IronPython URLs -- aggregator blog

Hello, Dynamic Language Runtime-enabled World! -- IronPython 2.0 now runs on Mono.  Shame that 1.2.4 came out about 24 hours before this was checked in.

Identity Providers, Authentication, Self-Issued cards

AD FS/SiteMinder integration via federation

Web Content Accessibility Guidelines 2.0 up for public review 

The implications of OpenID 

IronPython Console Syntax colouring and tab completion
tl;dr: ipy -D -X:TabCompletion -X:ColorfulConsole

IronPython Community Edition (FePy) -- at v1.1 with added tighter integration with CPython libraries.

Reducing User Interface Friction

Color Oracle -- colour-blindness simulator

Current Browsers and WCAG1.0

JavaScript -- the Lingua Franca of the web

1023 bit number factorized.  Time to move to 2kbits, and retire those decade-old PGP keys, I think.

Form validation with Prototype+Scriptaculous -- an example

Productivity tip -- not all Pentium-4 class processors are born equal.

Phew. Caught up

Monday, May 21, 2007

Links for 21-May

Getting there…

Sins of Software Security

Evolving the Web : HTML5 -- best viewed in Opera (latest public build) which supports some of the proposed new standard

Designing for Web 2.0 

JeffCroft.com: Elegant Web Typography (link to PDF)

Why "Why Functional Programming Matters" Matters -- A good thinking piece.

Consuming OpenID in Python (Django) web apps

Rails Live CD distro

amb special form -- non-deterministic (ambiguous) computation

"inherit" behaviour via expression in IE -- still working around the omissions

Designing Interfaces: Patterns for Effective Interaction Design

Patterns in interaction design

7 JavaScript techniques you should be using today

New Recommendations for Using Strings in Microsoft .NET 2.0

Rails style creators in Java

How to prevent HTML tables from becoming too wide

Conway's Game of Life in JavaScript -- utilizing the Canvas HTML extension for procedural graphics supported at least by Firefox 1.5, Safari 1.3, Opera 9.0 and later versions of these browsers. (It will not work on Internet Explorer.)

Barrier-Free Web Design -- The essence of Accessibility

The problem with Configurability -- Usability is sensible defaults, not a dial for everything.

Code is for people to read 

Strictness and correctness

An Initiate of the Bayesian Conspiracy

Economizing can be penny wise and pound foolish -- Is your code red, yellow or green?

Contrast and Meaning

Browsers will treat all HTML as HTML 5 -- Interesting conformance constraint for the new version

Programming Tip: Learn a graphics editor -- Always good to broaden your skill-set; especially when you have to fake-up UIs

The 128-bit programming challenge -- a piece of the zeitgeist.

Securing Orcas Workflow Services with& CardSpace

What is Good Software Design?

Illiterate Programming

Learn Prolog Now

Style matters

Programming Quotations

Programming Languages: Application and Interpretation -- e-book

More than just writing code

Can software be just like Lego?

SVG browser support

That catches me up to 9-May-07

Sunday, May 20, 2007

"-Wall" is misleading

So, what happens when we compile this code "-Wall"?

Not the answer you'd expect --

$ gcc -Wall test.c
$ ./a.exe
Whoops!
$

However, there are quite a few warnings in the gcc documentation that are marked as not being controlled by -Wall -- so let's turn on a bunch of them:

$ gcc -Wall -W -Wshadow -Wpointer-arith -Wcast-qual -Wcast-align -Wwrite-strings -Wconversion -Waggregate-return -Wstrict-prototypes -Wmissing-prototypes -Wmissing-declarations -Wredundant-decls -Wnested-externs -Werror -ansi test.c
test.c: In function `main':
test.c:8: warning: comparison between signed and unsigned
test.c: At top level:
test.c:3: warning: unused parameter 'argc'
test.c:3: warning: unused parameter 'argv'

Ah!  That's better.

By contrast

C:\temp\unsign>cl test.c /W2
Microsoft (R) 32-bit C/C++ Optimizing Compiler Version 14.00.50727.42 for 80x86
Copyright (C) Microsoft Corporation.  All rights reserved.

test.c
Microsoft (R) Incremental Linker Version 8.00.50727.42
Copyright (C) Microsoft Corporation.  All rights reserved.

/out:test.exe
test.obj

C:\temp\unsign>cl test.c /W3
Microsoft (R) 32-bit C/C++ Optimizing Compiler Version 14.00.50727.42 for 80x86
Copyright (C) Microsoft Corporation.  All rights reserved.

test.c
test.c(8) : warning C4018: '<' : signed/unsigned mismatch
Microsoft (R) Incremental Linker Version 8.00.50727.42
Copyright (C) Microsoft Corporation.  All rights reserved.

/out:test.exe
test.obj

C:\temp\unsign>cl test.c /W4


Microsoft (R) 32-bit C/C++ Optimizing Compiler Version 14.00.50727.42 for 80x86
Copyright (C) Microsoft Corporation.  All rights reserved.

test.c
test.c(8) : warning C4018: '<' : signed/unsigned mismatch
test.c(3) : warning C4100: 'argv' : unreferenced formal parameter
test.c(3) : warning C4100: 'argc' : unreferenced formal parameter
Microsoft (R) Incremental Linker Version 8.00.50727.42
Copyright (C) Microsoft Corporation.  All rights reserved.

/out:test.exe
test.obj

The Microsoft compiler takes the unsigned comparison as a level 3 warning, and that's what you get by default from DevStudio, with the unused argument warning at level 4.

So what's going on here?

Well in the comparison, the unsigned int is a "larger" type so a is promoted; but unsigned int is not actually any larger in terms of bits, so the bit value is preserved, and so a is interpreted as 2^32-1. Which is slightly larger than 1.

Some C and Java test and analysis tools

For static analysis of Java, the PMD tool (http://pmd.sourceforge.net/) can provide lint-like (or FxCop-like, depending on your exposure to these things) coverage of your source, with a configurable rule-set. It can generate its reports as part of an Ant build, and be integrated live into most Java IDEs to give live reports.

Like most of these tools, you will curse the first time you expose legacy code to it, and aim to clear the reports. In code that has to also play nice with .Net, you'll have to switch off two rules MethodNamingConventions and LongVariable; and some of its rules e.g. about empty default constructors cannot always be all consistently applied (so may need case-by-case suppression).

To go along with the use of JUnit test, Cobertura (http://cobertura.sourceforge.net/) is a coverage tool that works by instrumenting the Java bytecode of the generated classes. It provides Ant tasks (and thus can be manually inserted into any Ant based build system, such as NetBeans projects) -- instrument the normal output in a post-compile step, and run JUnit against the instrumented code.

This tool gives you line and branch coverage reports like this sample -- all the way down from package-level summaries to line-by line indications.

While most of this post is about Java, I might as well add to the pot a 'C'-based tool, Splint, which, as the name suggests, is an uprated lint-style tool, which includes in its analysis some basic probing for code that might be vulnerable to buffer overrun -- at least in cases when a buffer is passed into a routine without any length, and then gets written to.

I've not managed to track down any good free tools for C++ -- Microsoft's Prefast (at least as of 2 years ago) balked when fed code containing STL headers; other tools are 'C' only, or pay-ware. Given the syntactic complexity of C++, this is not so surprising.

The STL is your friend

Everyone knows this little idiom in 'C'

  char * array = malloc(string_length+1);
  if(!array)
  {
    // do something to handle allocation failure.
  }
  // do the real work
  free(array);

So the C++ equivalent must be

  char * array = new char[string_length+1];
  if(!array)
  {
    // do something to handle allocation failure.
  }
  // do the real work
  delete array;

Actually -- no.

The first bug is that having used new[], this must be matched by a delete[] (otherwise you will land yourself with interesting heap corruption to track down). The second is the behaviour of new when memory is not available.

Unless you have gone through some contortions to set up your build (in which case you know what you are doing), memory allocation is raised as exception std::bad_alloc -- so take 2…

  char * array = NULL;
  try {
      array = new char[string_length+1];
  } catch (std::bad_alloc) {
    // do something to handle allocation failure.
  }
  // do the real work<
  delete [] array;

Better, but you're still doing some of the heavy lifting yourself. Better yet is (assuming that you are working on the allocated space as a mutable buffer)

  std::vector<char> array; // zero length vector on the stack
  try {
     array = std::vector<char>(string_length+1);
  } catch (std::bad_alloc) {
    // do something to handle allocation failure.
  }
  // do the real work

or, if you're actually working with a string that is to be read from

  std::string array; // zero length string on the stack
  try {
     array = std::string(my_nil_terminated_string);
  } catch (std::bad_alloc) {
    // do something to handle allocation failure.
  }
  // do the real work

where the buffer management is handed over to code already written and tested to do the job for you.

Links for 20-May

The flood continues …

Solving FizzBuzz using compiler error messages -- or another example of how to use C++ templates as a functional programming tool

Redefining Professionalism for Software Engineers

JavaScript hijacking -- Interesting post and comment thread on poor idioms to use within AJAX/JSON type programming

Sandboxing JavaScript using <iframe> -- a technique to mitigate injection attacks

Hard-core customisation of Visual Studio 2005 -- here used to suppress the auto-generation of #region tags around automatic interface generation (which are a nice idea in theory, but soon turn into undocumentation in practice). Thinking of which

Avoiding Undocumentation -- an oldie, but a goodie

loglibrarian: How I Learn New Things These Days

UAC is for developers 

Don't have a COW, man? What Haskell teaches us about writing Enterprise-scale software -- It's surprising what light a functional language, with immutable values can cast on a problem

Optimizations That Aren't (In a Multithreaded World) -- however... (Damned if you do, damned if you don't...)

The "Yes is No" problem -- with dynamic languages, what you see in the source may not be what you get at run-time

Pick a license, any licence

Breaking 104 bit WEP in less than 60 seconds

CSSVista -- Live editing tool for CSS in Firefox and IE simultaneously

Concurrency Crisis -- Is vanilla OO the right tool for handling inherently concurrent systems?

Less programming -- more skill?

Ruby Threads considered worthless -- mainly because they are interpreter-level (aka green) thread, not ones known to the OS (though that does not apply to JRuby which uses the Java threading library instead.

JavaScript framework for Google Maps

More on HTTP.SYS and its security implications -- a must-read

Free icon sets

PPK on HTML5

Firefox as an IDE

Web 2.0 Accesibility

Typography -- compose to a vertical rhythm

The Language of Accessibility -- build it in, don't build barriers

Prioritizing Web Usabilty -- Jakob Nielsen's latest book

Ruby code that will swallow your soul  -- some of the tricks that that Evil Ruby (Extends Ruby's semantics by accessing its internals from pure Ruby code) can enable

Pattern matching with Ruby -- no, not regexes; but something much more fun

SoftCoding -- A dailty WTF essay piece that spots a problem but doesn't quite draw the lesson from it -- the lesson being that Abstraction is somewhat like Optimization.

What if web apps worked like pin-ball machines? -- an interesting view of web idiom

Markup as Craft -- aiming for maintainability and usability

Guidelines for creating better mark-up 

InfoCards and Identity Stability

CardSpace and Unique IDs 

Agile Project management and Competitive Advantage

From Abstraction to Zipf

What does Barbara Liskov have to say about Equality in Java? -- same reasoning applies in C#

Architect's notes for Varnish -- a different look at storage paradigms

The truth about Lisp

Token Description Service for Cardspace

Walking, talking and quacking in Java -- Duck typing and interfaces

When in doubt, make it public

Mount ISO as CD with a MSFT tool -- self extracting .zip with readme.

[Now playing - Uninstall]

Saturday, May 19, 2007

Anime — Gakuen Utopia Manabi Straight

About the only series that came out in Q1 that I followed -- and with great thanks to Anonymous who actually finished the subs, after it had been seemingly abandoned 3/4 of the way through.

Girls' high school, slice of life in the mid-2030s. Population declines, and schools are emptying. But one girl is not going to let her new school go quietly into that good night.

Cute, harmless. In all, simply nice.

Exceptions and their treatment

Depending on your preferred language, exceptions can vary from being scary black magic and an indication that all has gone horribly wrong ('C', even with Windows Structured Exception Handling), through to being familiar to the point of contempt (Java, C#).

As a rule of thumb, exceptions should indicate that, well, something exceptional has happened -- not that a user has said "No" rather than "Yes" at a particular interaction, but rather that a part of the infrastructure has not lived up to its expected contact (memory cannot be allocated; a network connection cannot be made). There is, even so, a grey area in the middle -- things like "File not found", where the low level code is reacting helplessly to the caller having not lived up to its side of the bargain -- where an exception generalises the concept of an error code.

When should an exception be raised (i.e. when should a throw statement appear in code)?  When something happens that the code at this point cannot sensibly deal with because it can't see the big picture.

When should it be caught? Two answers here -- first, when the code reached by the stack unwinding knows enough about what it is doing to be able to respond sensibly to the problem ("This file does not exist, please choose another"); secondly, when the code knows enough about what is going on that it can describe the error in a better fashion to the code higher up -- a process of catch, augment (or wrap), and re-throw.

So, what happens in the middle?

In some cases, what has happened is that the system has gone so horribly wrong that we might as well throw up our hands, and let the process terminate; in others, what has happened is essentially trivial (like file not found) so we really want to be able to pick up and continue.

How do we characterise the behaviour of the system, then, when we perform an operation that may throw?

There is an established terminology for this. We say that an operation has a basic level of exception safety if the remains in a consistent and usable state (no leaks, all objects valid) after the exception. The operation is strongly exception safe if after the exception is handled, the system has returned to the state before the operation began.

And some operations can be classed as not failing (and without them we would indeed be building on sand). Destructor/deallocator and assignment/swap operations must fall into this class -- without them we cannot reliably or safely perform any clean-up or recovery.

RAII (or using, or try/finally) is the idiom that (with no-fail deallocation) most cleanly supports the two weaker types of behaviour : this is where we can prevent resources leaking, and restore objects to a consistent state (if not always the original one).

The easiest way of ensuring strong safety, i.e. a roll-back to the original state is to do the all the operations with temporary variables. Only when all the tricky work has been done, do we mutate the external state, using (no-fail assignment or swap operations) -- any exception that could happen, happens before the objects are changed from their original pristine state, and roll-back is a no-op.

Working to improve the resilience of code under exceptions is another good reason to strive to separate responsibilities within the code -- a routine that has many effects, especially if some are dependent on others, can be more difficult to separate out into fallible and safe sections. As always, this is an ideal to be striven for, rather than an absolute -- consider the operation of popping a stack in C++, where the stack is mutated and an object (rather than an object reference) is copied.

Responsibility Driven Web Design

It has been suggested as a rule of thumb that debugging and maintenance is twice as hard as writing the code in the first place -- so writing anything that is truly as clever as you can manage guarantees that you'll not be able to fix it.

Taking a responsibility led approach means that each unit that you write has a clear reason to exist, and does a well defined job. Tweaking its "mission statement" or making it adhere to it is a task that only affects the system locally -- reducing the fears that some well intentioned change will have some subtle side-effect in a distant part of the system.

But responsibility driven design is not just about organizing your objects (as I posted about here) in a conventional code library or executable. It can be a general philosophy of design.

But web design? 

Yes.  The web -- and in particular, the vast bulk of user agents (browsers) out there -- has matured greatly in recent years, and support for techniques that let us apply a separation of responsibilities approach is now almost universal.

When HTML over HTTP first emerged, it was aimed to fill a rather restricted role -- publishing scientific papers on-line, doing away with the need to mail-shot out Xeroxed pre-prints; and it filled that niche well. But then it burst out from the academic to the commercial (and hobbyist) fields. No longer were sketchily formatted grey pages with various sizes of Times Roman acceptable -- the guys from the DTP world came on-line and tried to force what had been a set of hints about layout into a pixel-perfect replica of the paper-oriented world they were familiar with.

And around the turn of the century, there was only one way to do that -- to abuse the <table> element to force a grid model into what was by its nature a fluid medium. Tables within tables within tables, propped up by 1x1 transparent spacer gifs, borders supplied by setting the background in some of the cells, became the standard -- and to be fair, with the version 3 and 4 browsers, at the height of the browser wars (remember <blink> and <marquee>? -- things seen that cannot be unseen), that was the best that could be done.

So, it worked -- after a fashion. But, to paraphrase "d00d -- where's my content?"

Updating the content of a site generated in this style was painful -- and rebranding became an exercise in starting again from scratch.

This is where separation of responsibilities comes in.

Content and how it is structured -- the semantic value of the page -- can be separated from its presentation; and the behaviour of the page separated from both of them, by using the appropriate technologies for each; respectively HTML (or XHTML) for the content, CSS for the presentation, and (unobtrusive) JavaScript for the behaviour.

Separating the presentation out into CSS gives two immediate benefits -- first, it makes you think about how the meat of your page is structured; and second, it means that you are not forcing a 600-1000 pixel wide design onto the users of small form factor devices, and can see what users of text-only browser (including text-to-speech) users will see, gaining an immediate improvement in accessibility.

To assist with moving to the non-presentational page, writing and validating pages against XHTML 1.1 is good since it has almost none of presentational tags and attributes found in HTML 4.01 (though you should be aware that there are issues regarding the RFC-compliant correct MIME-type for serving this dialect -- cutting a long story short, you should theoretically only serve it as XML, but IE can't handle that).

These days, design can be targeted at browsers with good CSS support -- Mozilla browsers from ~2003 up, Opera 8+, Safari and IE7.  Then you can fix up for IE5-6 by using IE's documented conditional comment mechanism to feed extra CSS and/or Dean Edwards' IE7 scripts to adjust to fit. Earlier browsers -- far less than 1% of the web these days -- can be protected from all this by their lack of CSS support, and get the text-only version (perhaps with colour and font styling).