Thunderclap, the Newsletter of Rolling Thunder
Volume 4, Number 1 Autumn 2001
In this issue:
Feature Article: Using .NET for Easy, Painless Access to XML Documents
New Book: Introducing Microsoft .NET
Blatant Self-Promotion: New Training Class on .NET
The Internet Chuckle: The Ultimate Haiku
Contest with Prizes: Laws of the Universe
Results of Last Contest: How to Tell a Geek
The most pressing problem in today’s software industry is communication among different types of systems. The Internet is highly heterogeneous, and this heterogeneity will only increase as the Web continues to grow. It’s been easy for at least the last five years for a Microsoft box to talk to another Microsoft box, or a Sun box to talk to another Sun box. But communicating from a Microsoft box to a Sun box to a palmtop to a Macintosh to a cell phone to an intelligent refrigerator remains a very difficult but very important problem. Funny how those two always go together.
The most exciting and potentially profitable development in the last couple years is the use of XML as a universal wire format for communication among different types of systems, as English is used as a universal data format in international air traffic control. Machines communicate by exchanging XML documents which, since they are encoded using standard characters, any machine can read. The structure and contents of the XML documents used in a specific industry are regulated by standards agencies governing data communications for that industry, such as ACORD for insurance and HL7 for health care.
The main advantage of this approach is that it works at all. Nothing else does, at least not well. But creating, and to a lesser extent reading, an XML document requires you to write a large amount of very tedious code, even using an XML parser. XML parsers are by their nature highly generic, containing no knowledge of any particular type of document. So you usually wind up using XPath expressions to access data elements within the XML document. The code for fetching a single data value from an XML document looks something like this:
= DocOut.selectSingleNode _
This looks OK at first glance, and it definitely beats counting angle brackets yourself. But it’s actually quite annoying once you’ve done it for more than about half an hour. The XPath strings are very easy to get wrong, just use the wrong case for even one character and the whole thing crashes in flames. That’s the kind of bug that gets harder to find the more you stare at it. Smart tools such as Intellisense doesn’t work on it, so you have to keep flipping back and forth in your documentation to remember what fields are available and how are they implemented, for example, is this data field an XML element or an XML attribute. You’re constantly, expensively, and painfully thinking about the structure of your XML document, instead of your business logic.
Fortunately, the XML serialization capabilities of Microsoft .NET make this problem go away quickly and easily. These features abstract away the details of an XML document by presenting it as a .NET class. It makes your code much faster and easier to write and much harder to screw up, and you know how your developers just love to work with the latest and coolest tools. I don’t see a downside to it, as long as you don’t hold a religious loathing for Microsoft, and few of my subscribers do (I cancelled Janet Reno’s subscription just to be nasty.) The following explanation of .NET’s XML serialization features starts with the basics and proceeds in small increments, so you should have no trouble digesting it.
Suppose I have a .NET class called Point that represents a point in Cartesian space, containing two integer member variables called X and Y (stop me if I get too technical, OK?). The class looks like this:
Public Y As Integer
I’ve used VB in this article’s text because that’s what most of my readers speak, but the sample code that accompanies this newsletter contains a C# version as well as VB.
The .NET Framework provides a class called System.Xml.XmlSerializer.
An object of this class knows how to take a .NET object and write its
public data fields into an XML document. This process is known as serialization,
and I like to think of it as dehydrating an object and storing the
resulting powder. The same serializer can then take the XML document at a
later time, read its contents, and re-create an object of the same class
having the same values as the original object. This process is known as deserialization,
and I think of it as adding water to rehydrate the object. Here’s a
conceptual diagram of the process:
I’ve written a sample program that serializes and deserializes a Point object to the XML document of your choice. You can click here to download this application and the rest of this article’s samples. I wrote it with Build # 7.0.9344, provided to authors in September 2001. This means that users with the June Beta 2 release of .NET may not be able to run the samples. The later version contains enough differences from Beta 2 that I thought it more important to demonstrate them than to maintain compatibility with an old version. I don’t expect major changes from what I’ve written here to the final release version (famous last words). As always, your mileage may vary. The sample program looks like this:
I enter the X and Y values that I want for my Point object. When I click “Save”, the app pops up the dialog box for entering a file name. The app then uses the serializer to write the Point object into the XML document that I entered. The code looks like this:
sender As System.Object, _
ByVal e As System.EventArgs) Handles Button1.Click
' serialize Point object into.
Dim dlg As
If (dlg.ShowDialog =
' Make a new object of class Point
' and Y values specified by user.
Dim here As
here.X = TextBox1.Text
here.Y = TextBox2.Text
' Create XML document named by the user
Dim xmlstream As
' Make a new serializer for the Point
Dim serializer As
' Write (serialize) the Point into the
The resulting XML document looks like this (omitting declarations of unused namespaces):
OK, we’ve dehydrated our object into an XML document. How do we add water to reconstitute it? The reverse of this process is deserialization. The code looks like this:
sender As System.Object, _
ByVal e As System.EventArgs) Handles Button2.Click
' Pop up dialog box asking user which XML
' file contains the serialized Point object
Dim dlg As
If (dlg.ShowDialog = DialogResult.OK) Then
Dim xmlstream As
' Make a new Point object
Dim here As
' Make a serializer for the Point class
Dim serializer As
' Read (deserialize) the document into
the Point object
here = serializer.Deserialize(xmlstream)
' Place desired items into text boxes
TextBox1.Text = here.X
TextBox2.Text = here.Y
It looks like this serializer is doing something magical, but it’s really just a utility infielder. When you create the serializer object, it uses .NET’s reflection API to read the .NET metadata describing the public fields of the class that you pass in its constructor. When you tell it to serialize, it simply uses the reflection API to read the values of these public variables and read-write properties, and uses .NET’s generic XML parser to write them into an XML file. When you deserialize, it reads the XML document, creates a new instance of your object, and uses the reflection API to set its public data members individually to the values contained in the XML document. Now that you know what it’s doing, you won’t be surprised when I tell you that it only works on public read/write data members, and that it requires your object to have a default constructor (one that requires no parameters). I don’t have space in this article to describe the reflection process in detail; suffice it to say that it’s a relatively simply operation. Perhaps I’ll write about it in a future issue of ThunderClap.
OK, my .NET objects can go into and out of XML documents, which means that I can easily send objects over the wire from one .NET application to another because they share the same XML document layout. Big fat hairy deal. I don’t greatly care about talking to other instances of myself, I could do that with DCOM or MSMQ or any number of other Microsoft-specific techniques. I want to use XML to interoperate with other non-.NET and non-Microsoft systems, actually with any arbitrary system, how does this serialization nonsense help me do that?
Good question, here’s the answer. The .NET XML serializer allows us to control the layout of the XML documents that it produces by adding .NET programming attributes to our .NET class, as process known as "decorating the class". The example above illustrated the serializer’s default behavior of storing the class’s variables in XML elements. But what if we want to store the Point object’s data in XML attributes instead of elements? We can easily get this behavior by marking the member variables with the .NET programming attribute <System.Xml.Serialization.XmlAttribute()>. (C# uses square brackets rather than angle brackets to hold programming attributes. That language is truly nothing but VB with semicolons, or Java without Sun). A class representing a point but storing its data in XML attributes would look like this:
X As Integer
<System.Xml.Serialization.XmlAttribute()> Public Y As Integer
Programming attributes have nothing whatsoever to do with XML attributes; it's an entirely different use of the 'A' word. Programming attributes in .NET are a generic way of adding metadata to a .NET assembly or class. They are conceptually somewhat similar to the "public" and "private" keywords that you use to specify access permissions for your classes and variables, except that they describe other properties of their targets. This metadata can be inspected at runtime by other pieces of code to find out how to deal with the decorated class. Attributes are a powerful tool for .NET software development, and I'll probably write about them at length in a future issue of ThunderClap. When the serializer goes to serialize the object, it looks at the .NET attributes with which the variables are marked, and therefore knows that the integers should be stored as XML attributes instead of elements. The resulting XML document looks like this:
<PointStoredInAttributes X="5" Y="10" />
So now we can use XML attributes to hold the data in our .NET objects. We’re closer to being able to match any arbitrary document with a .NET class, but what about the case of .NET objects containing other .NET objects? Still no problem, the serializer properly handles hierarchical nests of objects. I suspect that it uses recursion internally. Suppose I have a rectangle that contains two points. The class definition would look like this:
Public Class Rectangle
Public UpperLeft As New Point
Public LowerRight As New Point
And the serializer would produce an XML document that looks like this:
The serializer will also handle arrays properly as well. Suppose instead of a rectangle, I had a generic polygon class containing an array of points. Using the attribute version so as to better fit the XML document on the page, I would write it like this:
Public Vertices() as PointStoredInAttributes
This class would serialize into the following XML:
<PointStoredInAttributes X="5" Y="10" />
<PointStoredInAttributes X="10" Y="15" />
<PointStoredInAttributes X="18" Y="10" />
<PointStoredInAttributes X="5" Y="29" />
[ etc., for however many there are]
The serializer even handles objects whose types can vary at runtime, as long as you provide it with a list of the possible object types it might see. You can write code that provides this list at runtime, but it’s tricky. Most often, you know at design time the complete list of possible object types that a variable might contain. You can then tell the serializer the list of allowable types by marking the variable with one <System.Xml.Serialization.XmlElement()> attribute for each type it might contain. Suppose I wanted to write my Rectangle object to accept an object of either class Point or PointStoredInAttributes for each corner. I’d write my class like this:
Public UpperLeft As Object
[ same for LowerRight]
At serialization time, the serializer will check each member variable against the list of allowable objects, and properly serialize whichever one it finds. If it finds a type of object you haven’t told it about, it will fail. The sample code accompanying this article provides a program that creates and serializes a rectangle containing one Point and one PointStoredInAttributes object. The XML document it produces looks like this:
<PointStoredInAttributes X="30" Y="40" />
So you can see that by using .NET programming attributes, we can control the XML document that a .NET object produces when it is serialized and from which it can be reconstituted. Conversely, if we know the structure of the XML document that a client sends us, we could write a .NET wrapper class that would properly wrap itself around that type of document. We wouldn’t have to write all that tedious, expensive, buggy generic parser code with its annoying XPath expressions. Instead, we’d just create a .NET object of the proper class, deserialize the incoming XML document into it, and read its values from the object’s member variables. To create a response document, we’d simply create a .NET object of the proper class, set its values, and serialize it into an XML document. Again, no more generic parser nonsense. We know the structure of the XML documents from the standards agencies, that’s why they exist. The only drawback is that writing, testing, and debugging this wrapper class looks like it would consume time and money, possibly a lot of both if the document were complicated, and most of the interesting ones are.
No problem. Generating a wrapper class for an XML document is such a common repetitive operation that the Microsoft .NET SDK comes with a tool that does it for you. It’s called XSD.exe, the XSD schema tool, and you run it from the command line window. The description of an XML document is contained in a schema, often generated by the standards agency that controls the XML document layout. If you feed XSD.exe a schema, it will generate the wrapper class that goes around the document described in that schema. The screen shot of doing it looks like this:
Here's an example from the insurance industry. The standards organization for the insurance industry is ACORD, online at www.acord.org. ACORD publishes XML communication standards for life insurance, property and casualty insurance, and reinsurance. A sample document using the life insurance standard looks like this:
<FullName>Bond, James </FullName>
<GovtID> 007 </GovtID>
<EstNetWorth> 1234000 </EstNetWorth>
[ other elements of a Party. …]
[other Parties, and other types of elements …]
The schema for this type of document is quite large, 460 kb and rising. Writing your own wrapper class for this would take forever, and you’d never get it all correct. But I fed their schema into XSD, and hey, presto, out came the set of wrapper classes in about 5 seconds. Here’s a small excerpt of the class that describes a Party, with the uninteresting bits removed:
Public Class Party
Public FullName As String
Public GovtID As String
Public EstNetWorth As Decimal
Public EstNetWorthSpecified As Boolean
I wrote a sample program that reads and edits an XML document using the wrapper class I generated from the schema. The sample application looks like this:
It opens the document and then looks for all the objects of class Party, which it puts into the list box for you to see. The wrapper class for the root object uses a form of the XmlElementAttribute declaration (synonymous with XmlElement) that passes an alias string, so that the element named <Party> produces an object of class Party and vice versa. The root object’s declaration (uninteresting pieces removed) looks like this:
System.Xml.Serialization.XmlElementAttribute("Party", GetType(Party)), _
[ others element types omitted] > _
Items() As Object
The code for reading the document and populating the list box with parties looks like this:
CurrentDoc As New
Private serializer As New Xml.Serialization.XmlSerializer(GetType(OLifE))
Private CurrentParty As Party
Private DocumentFileName As String
sender As System.Object, ByVal
e As System.EventArgs) _
[dialog box code omitted]
' Read (deserialize) the document
CurrentDoc = serializer.Deserialize(xmlstream)
' Place Party items into list box
Dim item As
For Each item In CurrentDoc.Items
' Check to see if the object is a party
' If it is, put it in the list box
If (item.GetType Is
“Not so fast, Plattski,” said one student when I showed him the code above. “I saw you palm that card, putting an object into a list box. What are you trying to pull here, eh?” (The guy was Canadian). The list box in .NET can hold objects of any type. The string displayed in the list box is the string returned from the object’s ToString method, which every .NET object inherits from its System.Object base class. To make this sample work, I had to override my Party’s default ToString method, which required adding the following code to the Party definition in the wrapper class file:
Overrides Function ToString()
Putting an entire object reference in the list box makes it a whole lot easier than having to put in a string and manage a separate collection of attached data using the ItemData property, doesn’t it? The only thing you have to worry about is losing the code you've written if you generate the wrapper class again and clobber your original file.
When the user clicks on an item, we fetch the Party from the list box and populate the text boxes showing the GovtID and EstNetWorth. The code looks like this:
sender As System.Object, _
ByVal e As System.EventArgs) Handles ListBox1.SelectedIndexChanged
If (Not CurrentParty Is Nothing) Then
TextBox1.Text = CurrentParty.GovtID
' Put party's EstNetWorth in its text box
(CurrentParty.EstNetWorthSpecified = True)
TextBox2.Text = CurrentParty.EstNetWorth
Many elements in the ACORD document spec are optional. Accordingly (groan), it is important to be able to distinguish the absence of an element from the presence of the element with an empty value. For example, the absence of <MiddleName> means that you have no idea what the guy’s middle name is. The presence of this element with an empty value means that you do know exactly what the guy’s middle name is, and the name is blank. (I knew a guy like that once. He had more blanks than just his middle name.)
For data members that are reference types, such as strings, arrays, or other objects, if an element is absent from the document, its variable in the wrapper class will contain the value of Nothing (null for you C# geeks). For example, in the sample document you downloaded, Speed Racer’s GovtID element is absent, so Nothing gets assigned to the TextBox1.Text in the code above. That’s not a problem, the text box can cope with it. If the value remains Nothing when the class is serialized into an XML document, then the element won’t be written. If the string is indeed present, then an element containing its contents, possibly empty, will be written into the document. It works about the way you think it should. The serializer does a good job of complying with the Principle of Least Astonishment, which states that astonishing the user is generally a Bad Thing, therefore you should do it as little as possible. [Note: This default behavior is a change from Beta 2, which required significant work on your part to obtain the non-astonishing behavior.]
Handling data stored in value types such as numbers is different, because the value type can’t be set to Nothing as a string or object reference can. Therefore, the wrapper class generator adds a boolean variable to the wrapper class that tells you whether a numeric value was or wasn’t present in the document you read, and should or shouldn’t be present in the document you write. The name of this variable starts with the name of the element it corresponds to and tacks on the string “Specified”. In the example above, you can see that my XML document contains an element called <EstNetWorth>. The wrapper class contains a variable of type double called EstNetWorth, containing the numeric value of the element, and a boolean called EstNetWorthSpecified, which tells you whether EstNetWorth is any good or not. If the element was present in the document, it will be set to true, otherwise it will be set to false. When you want to serialize the document, you set it to true if you want its corresponding value element written into the document, false if you don’t. The flag itself is never serialized into the document because it’s marked with the XmlIgnore attribute. So I’ve written the code for the text box that edits the net worth to set it to true if the text box contains any text, and false if it doesn’t, as shown here:
sender As System.Object, _
ByVal e As System.EventArgs) Handles TextBox2.TextChanged
(TextBox2.Text <> "") Then
CurrentParty.EstNetWorth = TextBox2.Text
CurrentParty.EstNetWorthSpecified = True
CurrentParty.EstNetWorthSpecified = False
Writing code using the wrapper classes is a snap compared to using a generic parser. The compiler will catch me if I misspell a variable. And I don’t have to switch back to my docs because it has full Intellisense support, as shown in this picture. That’s the coolest thing imaginable.
To summarize, XML is the standard universal wire format for data between disparate systems in the heterogeneous Internet world. Generic parsers are quite tedious to use for large programs. Microsoft .NET makes it easy to generate a wrapper class that lets you treat a document as a .NET class. This makes it much, much, as in night-and-day, easier to program. Even so, there are still issues to deal with, such as the proper use of namespaces with wrapper classes. I've removed these pieces from the source code listings in this newsletter as the clutter it up without explaining things, but they do start to matter once you start digging deep. And the switch to .NET, while well worth the effort, requires a significant learning curve. I’d be happy to come to your company and teach you all about .NET. You can read about my .NET training classes here on my Web site .
We'll continue our discussion of .NET in the next issue. Enjoy playing with your new attribute program. Give me a call if I can help you out. Until next time, as Red Green would say, "Keep your stick on the ice."
New Book: Introducing Microsoft .NET
by David S. Platt, President of Rolling Thunder Computing
Published by Microsoft Press
I've done it again. I'm so busy teaching that I don't have time to sneeze (OK, I manage to squeeze it in occasionally). So what do I do? Like an idiot I signed up with Microsoft Press to do another book, this one on .NET. It's similar in content and style to my earlier Understanding COM+, and aimed at the same readership. It is meant to be accessible to managers, while still providing enough information to be useful to programmers, both lightweight VB types and heavyweight C++ types. The book is meant to be non-threatening, using a lot of pictures and diagrams, a small amount of simple VB code, and no C++ at all, which would scare off 80% of the potential readers. I write each chapter in a pyramidal structure, so managers can read the first three sections (Introduction, Problem Background, Solution Architecture). Ambitious managers and VB programmers can continue through the next section (Simplest Example). Heavier-duty developers can read the ends of the chapters, where I discuss more advanced elements of the topic. The book's Web site is, naturally, www.introducingmicrosoft.net. There you will find a free chapter on ADO.NET, as well as the code for all the book's samples, and a list of errata as soon as we find some. You'll also find a glowing review of it here (well, what other kind did you expect me to link to? I may be crazy, but I'm not stupid.) written by Manohar Kamath. Here's the table of contents:
|5. Windows Forms|
2. .NET Objects
|6. Epilogue and Benediction|
|7. Added Bonus -- ADO.NET Chapter available free online.|
4. .NET Web Services
The book was officially released on May 11, and should be on shelves now. On June 11, its sales rank on amazon.com was #762, thumping Tom Clancy's latest hardcover and paperback, hopelessly mired around #1400. That tells you something about Amazon's customers -- they're all geeks.
Blatant Self Promotion
WORLD TRADE CENTER CHARITY BENEFIT
Public Three-Day Class on ACORD XML for Insurance in New York, Dec 11-13.
Sponsored by Rolling Thunder Computing, ACORD, MetLife, and IBM
Every dollar paid by attendees will be donated to World Trade Center attach relief charities. This 3-day training course is designed to educate the technical person on XML and the ACORD XML standards for both P&C and Life insurance. It gets beyond the hype and teaches programmers what they need to know about this technology standard. Register with email@example.com.
One-Day Public Seminar on .NET, in Boston on November 17
Come see me cover all of .NET in a single day, Saturday November 17. It's sponsored by the Greater Boston Chapter of the ACM, held at MIT room 34-101, from 8:30 - 4:30. Syllabus and registration information at www.gbcacm.org.
5-day Public Class on .NET in Canada.
Two instances, Nov 26-30 in Toronto and Dec 3-7 in Moncton NB
These classes are being managed by Broadleaf. Details are at www.broadleaf.ca. Anyone can come, you don't have to be Canadian. The price of C$ 3000 is roughly US$ 2000, less than it would cost you in the US, and travel there is cheaper too. And if you're spooked about flying so soon after September 11, you'll have to admit that Air Canada is probably much less of a target for bad guys than any US airline.
5-day In-House Training Class on .NET or .NET for Insurance
.NET is here, and it's hot. It changes everything in the software business, and you can't afford to be without it. Rolling Thunder Computing now offers in-house training classes on .NET, using my book as the text. See the syllabus at www.rollthunder.com/dotnetfiveday.htm
4-Day In-House Training Class on XML or XML for Insurance
You've probably been hearing an enormous amount of hype these days about XML. It sounds like a great idea, and it is indeed a beautiful solution to certain classes of problems. This four- or five-day training class covers the guts of XML, such as well-formed documents, validating documents with DTDs or schemas, programming XML using DOM and SAX, and transforming XML with XSL stylesheets. Most important, we talk about how to use XML in real-life applications: the advantages and drawbacks, the places where it fits well, and the places where you'd be trying to bang a square peg into a round hole. Get your reservation in quickly, because this one looks hot. You can read all about the new XML class on Rolling Thunder Computing's web site, http://www.rollthunder.com.
Internet Chuckle: One Amazing Haiku
I've always admired haiku, the Japanese poetry form of three verses, with 5, 7, and 5 syllables. I actually ran a haiku contest in Thunderclap a while ago, which was won by Tana Sabatino. You can click here to see the winning entry. The chuckle for this month is what has to be the geekiest haiku ever written, or ever to be written. You may remember that not long ago, the DVD manufacturers association developed an encryption scheme that they thought would keep their products safe from prying eyes. And it did, for about 5 minutes, until a trio of hackers reverse-engineered a software player, cracked, and published the decryption algorithm. The CCA sued, trying to keep it secret, but we all know that's impossible. There is today some legal question as to whether source code is or is not a protected form of speech expression. But that doesn't matter, because some person (it was submitted by anonymous remailer, so no one is really sure of the author) wrote it in the form of haiku. You can find the whole thing at http://www.cs.cmu.edu/~dst/DeCSS/Gallery/decss-haiku.txt. It consists of 459 triplets. I had a terrible time selecting just a few triplets to illustrate the cleverness of the poem and make you want to read it. If this isn't an art form, I don't know what is:
|Now help me, Muse, for
I wish to tell a piece of
|once secret, as all
knowledge, once unknown: how to
|for which the lawyers
of DVD CCA
don't forbear to sue:
start with zero and count up
from there, don't forget!
|that they alone should
know or have the right to teach
these skills and these rules.
|Integers are four
bytes long, or thirty-two bits,
which is the same thing.
|(Do they understand
the content, or is it just
the effects they see?)
|To decode these discs,
you need a master key, as
hardware vendors get.
|And all mathematics
is full of stories (just read
Eric Temple Bell);
| (This is a "player
key" and some folks other than
vendors know them now.
|and CSS is
no exception to this rule.
Sing, Muse, decryption
|If they didn't, there
is also a way not to
need one, to start off.)
The instructions follow, including indented loops, and liberally sprinkled with amusing asides and cries to the heavens in the name of freedom of expression. For example:
|But wait! I hear a
voice entreating me to stay:
"O, the Tables tell!"
|Number. Their inner
logic, aitia, telos,
still unknown to me.
|Alas, I have not
as yet declared to you the
|Herein a clear free
speech question: would courts see fit
to muzzle me, then,
|This is a major
issue, in that I don't know
what these tables _mean_:
|from speaking numbers,
technical data, which I
did not make and more
|our noble guide has
told us in outline what they
are for, or something
cannot explain in detail,
|of their structure. But
to me, a humble poet
|I have these numbers.
They have meaning, this is clear:
else why suppress them?
|they are opaque, they
are certain combinations
of ancient, noble
|I wish to speak or
let the Muse announce through me
Tables of Numbers.
You must read the whole thing. You MUST. And in response to the anonymous author, whoever he, she, it, or they may be, I can only say (in haiku, of course):
|Someone with enough
time on his hands to write this
must have no mortgage.
|I am astounded
Awed, amazed, flabbergasted.
Ye gods, what a geek.
Disclaimer: This section will often refer to commercial vendors of products or services. Rolling Thunder Computing receives no benefit from these vendors in any way, shape, form, or manner; and would decline any if offered. The sole criterion for mention in this section is that I laughed at it, and that I think people as sick as I am would do so as well. If you know a good one, send me the URL at firstname.lastname@example.org. If I use it, I'll send you a Rolling Thunder Computing coffee mug, which makes an excellent specimen container when your company implements mandatory drug testing.
Contest with Prizes: Laws of the Universe
Lord, send a man like Robbie Burns to sing the Song o' Steam!
-- Rudyard Kipling, "McAndrew's Hymn", 1894
I'd settle for Dr Seuss, except he's dead.
-- David S. Platt, "Plattski's Musings", 2000
When I was younger, I thought the universe operated according to laws. Then I decided it didn't, that anything involving human beings was ineradicably chaotic. Now I've swung back to the notion that it follows laws, except they're different laws than I first thought. For example:
Platt's First Law: Exponential Estimation Explosion. A software project always takes three times as long to complete as your best estimate, even if you apply this law to it.
Platt's Second Law: The Dungheap Principle. The amount of crap in the universe is conserved. If you have less crap to deal with, it's because you managed to dump it on someone else's head.
Platt's Third Law: Non-equivalence. Two can live as cheaply as one for half as long.
I'm sure you have your own ideas as to the fundamental underpinnings of the universe. So send them here to me, and I'll publish your wisdom for all to see. As always, your entries must be computer-related and original. This isn't a family newsletter, so they don't have to be clean or politically correct. Submitting more than one increases your chances of winning. First prize is $100, second prize $50. Winners will be announced in the next issue of Thunderclap, and the judge's decision (mine) is final. In the event of duplicate or similar entries, the earliest wins. All entries become property of Rolling Thunder Computing. All authors will be identified by first and last names, but not by company. Authors names will be withheld if you so request. Submit your entries via e-mail to email@example.com.
Results of Last Contest: How to Tell a Geek
First Prize, $100 to Tim Shuttleworth
Sometimes a picture is worth 1000 words. This one is worth $100, to Tim Shuttleworth, who submitted this picture with the following caption: "Attached is a picture from my recent trip to dive 'the Great Blue Hole' off Belize. Your book made the 3-hour boat ride a constructive use of time." There, my friends, speaks a geek.
Second Prize, $50, to Carolyn Sutton
You can't use a calculator that doesn't use RPN.
And Honorable Mention to All:
You know more than 6 ways to clear a register and which is the fastest ( XR R0,R0 )
You take your laptop on vacation with you.
When you go to a casino, you play video Blackjack/Poker instead of sitting at the tables with real people.
You own a copy of the movie "Tron".
You still have your punched cards from when you took Fortran.
You can translate ASCII in your head.
-- Carolyn Sutton
You know who won the JavaBowl, but not the SuperBowl.
You can run your toaster via Bluetooth/X10 from their PDA.
You pour Jolt Cola on your corn flakes (possibly a redneck geek).
To teach your children octal, I suggest taping three of their fingers together, so they can count them as one. Remind them to start counting at zero, and tell them that their hands are collections of fingers, their fingernails are attributes, finger snapping is an event, etc.
-- Phil MacArthur
Your audio cassette collection still contains more Commodore 64 games than 'The Commodores' tapes.
Peripheral vision to you means printers for as far as the eye can see.
-- Garry Evans
This is the tenth issue of my (more or less) quarterly newsletters. Each will bring you a technical article on current topics in software development, which I hope you will find useful. Each will also bring you a contest, allowing you to show off your intelligence and creativity to win prizes, which I hope you will find funny (although some readers have reported the reverse.) In between you will find my own blatant self promotional material, telling you about the latest ways I've come up with to separate you from your money. (I could have said "carefully selected products and services that we feel might interest you", or other mealy-mouthed horsepuckey. You want the truth or you want me to waste my time and yours dressing it up?)
I'd like to hear what you think about this newsletter and what types of articles you'd like to see in the future. Send your e-mail comments to firstname.lastname@example.org.
This newsletter may be freely redistributed, provided that it is sent in its entirety. If you enjoyed it, can I ask you to please forward it to a friend who might also enjoy it? The subscription roll has grown to over 4000 for this issue.
Thunderclap is free, and is distributed via e-mail only. We never rent, sell or give away our mailing list. Subscription and unsubscription are handled by a human operator reading e-mail messages. To subscribe or unsubscribe, jump to the Rolling Thunder Web site and fill in the subscription form.
Thunderclap does not accept advertising; nor do we sell, rent, or give away our subscriber list. We will make every effort to keep the names of subscribers private; however, if served with a court order, we will sing like a whole flock of canaries. If this bothers you, don't subscribe.
Source code and binaries supplied via this newsletter are provided "as-is", with no warranty of functionality, reliability or suitability for any purpose.
This newsletter is Copyright © 2001 by Rolling Thunder Computing, Inc., Ipswich MA. It may be freely redistributed provided that it is redistributed in its entirety, and that absolutely no changes are made in any way, including the removal of these legal notices.
Thunderclap is a registered trademark ® of Rolling Thunder Computing, Inc., Ipswich MA. All other trademarks are owned by their respective companies.