blog

Pre tag madness

May 17, 2003 12:40:18.329

Well, that was maddening. I've noticed that using pre tags (to escape code posts) has caused me grief here. I just figured out why. For presentation purposes, the server converts all CR characters into <br> tags. That's what I wanted - but it used to wreak havoc with tables I'd post - having br tags scattered through the table caused all sorts of interesting display issues. So I had the server look explicitly for table tags, and not convert within them. Turns out that doing the same with the pre tags gets rid of some presentation glitches as well. The joys of HTML....

 Share Tweet This

examples

AspectAdaptors and BufferedValueHolders - what are they?

May 17, 2003 12:09:51.579

I used to teach the ParcPlace Introduction to Smalltalk Class. Years later, I remember what used to happen on Wednesday when AspectAdaptors came up - a collective huh???, followed quickly by a blank, glazed-over-eyes stare. The confusion hasn't eased over the years; I still see many questions on this, even from experienced Smalltalkers. So what are they, what are useful for, why do you want them?

Well, consider a simple VisualWorks application - a class Counter with one instance variable - count. Here are some methods:


count: aNumber
     count := aNumber.

count
     ^count.

add: aNumber
     self count: self count + aNumber.

All pretty simple, right? Now let's have a UI on that - a simple UI that shows us the current value of the count, and gives us a button - each time we press the button, we send #count: to the Counter instance with an argument of 1. easy to enough to string together, but how do we get the UI to be aware of the changed value in the count variable, and display the new value? Well, there are two routes to follow - the MVC dependency model, and the new trigger event system. Here I'm going to use the MVC model - I'll post an alternative using events in the future.

Ok, so the first thing is to change the #count: method as follows:


count: aNumber
     count := count + aNumber.
     self changed: #count with: aNumber.


Ok, that signals a change in the Counter object - but how does the UI pick it up? Well, one (complex) way would be to make the UI a dependent of the Counter object, and then implement an #update:with:from: method. This method might look like this:


update: anAspect with: aValue from: aModel
     anAspect = #count
          ifTrue: [self counter value: aValue].

There's an obvious problem with this - as the number of objects of interest (in the domain and in the UI) grows, the #update method grows into a complex case statement. There's got to be a better way, right? It turns out that there is - AspectAdaptor. This object does exactly what the name sounds like - it adapts messages that are sent by the domain into ones that are understood by the UI. If you used the VW GUI builder, and your UI class has an input field for displaying counter, then you have a method that looks like this:


counter
     	"This method was generated by UIDefiner.  Any edits made here
	may be lost whenever methods are automatically defined.  The
	initialization provided below may have been preempted by an
	initialize method."

     ^counter isNil
          ifTrue: [counter := 0 asValue]
          ifFalse: [counter].

That's defining a ValueHolder - a wrapper around a number in this case. We want to replace that with an AspectAdaptor. Here's what that looks like:


counter
	"This method was generated by UIDefiner.  Any edits made here
	may be lost whenever methods are automatically defined.  The
	initialization provided below may have been preempted by an
	initialize method."

	^counter isNil
		ifTrue:
			[counter := (AspectAdaptor forAspect: #counter)
							subjectChannel: self model;
							subjectSendsUpdates: true]
		ifFalse:
			[counter]

That assumes that you have a line like this in #initialize:
model := Counter new asValue.

So what does the adaptor do? It sets up the communication channel for dependency updates for you automatically, on a per-object basis. The adaptor is now a dependent of the Counter object, and is specifically looking for the #counter aspect when updates come through. Note that the aspect is set to #counter - it's entirely possible to have the get/set messages be different. But AspectAdaptors are more than one-way conduits from the domain up - they are also conduits from the UI down. If you allow user input, a change in the UI will be pushed to the domain. Have a look at the class comments for AspectAdaptor and ProtocolAdaptor (its superclass) to see what's going on.

What if you don't want changes going down as each field on a form is changed though - what if you want a form level update? Have a look at BufferedValueHolder. You can use that to control when updates flow down, via a true/false switch.

This is all documented in the GUI developers guide as well - you should read that over for a more in-depth explanation. If you have questions, send them to me

 Share Tweet This

humor

Dilbert on management

May 17, 2003 11:06:42.966

Today's Dilbert strip skewers the multiplicity of management theories - but I think it could just have easily been skewering development methodologies....

 Share Tweet This

xp

Keith Ray on TDD Resources

May 17, 2003 10:56:43.843

Interested in TDD (Test Driven Development)? Check out Keith Ray's post on available resources.

 Share Tweet This

xp

Keith Ray on TDD Resources

May 17, 2003 10:56:43.843

Interested in TDD (Test Driven Development)? Check out Keith Ray's post on available resources.

 Share Tweet This

movies

ROTFL - The Matrix Reloaded and GPL

May 17, 2003 9:48:27.857

Charles Miller explains how Agent Smith has re-licensed himself using the GPL. Hehe.

 Share Tweet This

itNews

Companies gunshy towards IT

May 17, 2003 9:45:35.876

There's a nifty piece over at Loosely Coupled on the current attitude towards IT spending. The basic problem - after so many promises, companies are a little unwilling to invest in the next big thing - because the last big thing didn't rally deliver. Here's the idea:

Loosely coupled architectures enabled by web services are going to bring the same waves of incremental innovation in IT - and in business - and the only IT that is going to be shown up as not working is the highly structured and centrally controlled architectures of monolithic, enterprise-scale computing systems, whose design philosophy owes more to the values of the industrial era than to the needs of the emerging information era.

Unfortunately, as I noted recently after listening to a debate on the potential value of investing in web services, "Businesses have had so many false bounces in the bear market of IT expectation that they just can't bring themselves to buy any more." John is right to speak of a "backlash". In many organizations, that backlash is going to throw out the baby of distributed services innovation along with the stale bathwater of inflexible enterprise-scale computing, just at the very moment when businesses should be buying into the new distributed architectures.

He's probably right about the benefits of web services - they offer the opportunity of stitching together truly best of breed systems from component parts, instead of the dangerous all in one nature of past promises. Can you blame companies for being gunshy though? Look at it from the business side - the IT group has switched technology bases how mahy times since 1993 - and, in terms of business benefit - to what end? Tons of money was spent on Java conversions, for instance - and the best end result of that was for the IT shops to end up right back where they started before the conversion. Again, from the standpoint of the business folks, what did all that spending accomplish? Precious little, which is why they are so unready to invest more - especially in a down economy.

 Share Tweet This

tv

Top Ten Buffy Moments

May 17, 2003 1:46:49.033

Via Dewayne Mikkelson I found this top ten Buffy moments list. It's a good collection; not a lot to argue with. Go check it out.

 Share Tweet This

events

Smalltalk Solutions 2003 - Schedule online

May 16, 2003 16:57:09.976

The schedule for Smalltalk Solutions 2003 in Toronto is online. We will have this posted to the Smalltalk Solutions site shortly - in the meantime, check out the list of speakers, and go register!

 Share Tweet This

events

Cincom Smalltalk Events in Germany

May 16, 2003 14:09:28.190

There's going to be a roadshow in Germany this summer - check back to that site, the content will likely have more information by early next week. If you'll be in Germany in June, check it out

 Share Tweet This

rss

XHTML instead of escaped markup.... why?

May 16, 2003 12:59:09.560

I'm reading along in the Sax.NET blog, and stumble across a screed on why RSS should mandate XHTML instead of escaped markup. Sigh. Not this silliness again. On the one hand, this guy quotes Don Box:

Escaped markup has more momentum and history. It's the easy path if the goal is to ratify the vast majority of feeds currently on the Internet. XML-based markup (XHTML or otherwise) requires more courage, energy, and time. I personally think the upfront investment will reap pretty significant rewards pretty rapidly, but ultimately, it takes a village to pull this off.

He agrees with this. But hang on a sec - XHTML will require more time and energy, and there's no tool support. Escaped markup is, what - esthetically unpleasing? It works, browsers (and other tools) understand it fine. XHTML is harder to produce, and tools don't support it. There's a simpler question though - to the end consumer of a feed, what's the benefit? None. That's right, none. It will look the same either way. What about developers? Well, there's a need for new tools. Here's my question: why bother? Here's the justification:

I agree 100%... RSS is all about not allowing markup to sacrifice the structure of information. Mandatory XHTML will make RSS stronger and more useful. With XHTML markup we can have the best of both worlds: rich, creative expression, and unlimited, deep querying, indexing and transformation of the information.

Yeah, sure. An XHTML based markup will support the possibility of additional things layered on - but it seems like an awful lot of work for a presumed benefit. IMHO, it's not the simplest thing that could possibly work....

 Share Tweet This

smalltalk

And More - Smalltalk vs. Java and .NET

May 16, 2003 12:34:14.502

Over in cls, Lance Parkington weighs in with more on Smalltalk, .NET, and Java:

  1. Please note that Smalltalk (VisualWorks) does NOT wreck development machine a major saver of developers time! dotNET makes a complete mess and trashes the Windows Installer so VisualAge 3.5.x/4.x cannot be installed and probably little else can be installed successfully (ie anything using the Windows Installer) without manually editing tables in the .msi files. Also Sun's JDK's will then no longer work regardless when installed so pure Java cannot be used/tested after dotNET installed. To test dotNET applications really needs machine not installed with the development environment! This is considerable overhead.
  2. Java Bean development (public serializable classes) probably best carried out using VisualAge since generated code can be pushed through the Sun JDKs (pure Java). Generally Java takes 3-7 times as long to program same application as Smalltalk. This is partly due to need to define TYPE of variables before use requiring more thought, difficulties processing collections (no SortedCollections in Java out of the box), and general syntax issues (eg semi-colon, bracket emplacement). There is also more code in Java required to represent same functionality as in Smalltalk and this has knock on effect on productivity ie number of correct lines of code produced per day. Complex mathematical or logical classes will take long time to write and debug. It is also possible to save classes that have failed to compile in Java causing problems when applications cannot run! J2EE is generally too complicated and unreliable for everyday use and standards do not appear consistent in the major implementations!
  3. Smalltalk is generally the most productive language of all but suffers since expensive for academic/commercial use and poor support is available on the web for some of the more complex applications. There are very large gaps of information between introductory concepts (eg the Manchester archives) and advanced capabilities of current software vendors offerings (hidden in huge PDF files) that hardly see the light of day. Java support is generally better and if programmer is stuck it is generally quite easy in Java or C++ to find out quickly how to do something. Time and money are everything and gold plated solutions cannot be afforded when quick results are required by yesterday!

Things are better on the Smalltalk code front - for VW, check the VW Wiki and the public store. There are a fair number of Open Source projects going on in VW, being tracked in the public store. As to PDF files, Google indexes those - try a search.

 Share Tweet This

smalltalk

More on Smalltalk vs. Java

May 16, 2003 12:20:51.178

I posted earlier on a cls thread discussing Smalltalk, Java, and productivity. Alan Knight weighed in:

As I recall, although I heard the quote in a different context, he was specifically referring to working in VA/Java, which is as close to a Smalltalk environment as you can get in Java.

A couple of other celebrity testimonials grin

I firmly believe that there are two types of developers: Smalltalk programmers and everyone that wasn't lucky enough to be a Smalltalk programmer. Smalltalk is my language of choice because it is pure OO - you have objects and you send them messages, that is all. In Smalltalk, even classes are objects. Scott Ambler, author of a great many technology books (and a keynote speaker at ST Solutions 2003). This bit goes on at some length.

Although it's now a long time since I did anything with it, I nominate Smalltalk, I still haven't come across anything quite like it for being able to transfer thoughts into computer code. It's not just the language: It's the wonderful browser environment, the libraries, and the culture of writing clear, well-designed code as quickly as anything else can crank out spaghetti. When the participants at JavaOne were extolling how Java was so much more productive than anything else, I needed a brown paper bag. Oh well, back to sorting out my classpaths... Martin Fowler , (Software Development Magazine , Jan 2001)

So, Bob Martin's prediction for this decade: Keep an eye on languages like Python, Ruby, and Smalltalk. They are likely to become extremely important. Robert Martin, of ObjectMentor, one of the leading Agile/XP training companies.

"My absolute favourite language is Smalltalk." Grady Booch Software, Development Magazine, Sept 2002. (Of course, Grady immediately follows this with "I only wish it had survived". Fortunately, rumours of our death are greatly exaggerated).

See also Ed Klimas' site, where Ed Klimas, who does a lot of work with function point measurement on projects his company is involved with, has a quick summary.

More good stuff. There seems to be a pattern here....

 Share Tweet This

development

Keith Ray has a blog

May 16, 2003 11:53:35.463

Keith Ray has a blog I didn't know about this morning until he sent this comment to this blog. Check it out, and grab his feed here

 Share Tweet This

development

Blog transience

May 16, 2003 11:07:15.036

Rich Demers points out that blog posts are transient. Even with the search function, that's true enough - it's not as if I've been entirely consistent in my categorization, and it's hard to find something if you have no idea what you are looking for anyway. Why Smalltalk is a great place for Smalltalk articles - but not everything is going to end up there. In the meantime, I've got a small list of VW tip posts I've made here.

 Share Tweet This

examples

How to recover from a saved mistake

May 16, 2003 10:15:08.973

A few days ago, I added module support to BottomFeeder - and I made a fairly dreadful mistake in data classification. With the pubDate or dc:date items, you get sent a timestamp in either RFC822 or ISO8601 format. At the time, I was lazy and just kept thos timestamps in a string format. This is problematic on a few levels:

  • It screws sorting by date up - because a string sort won't necessarily be the same as a date sort
  • Inconsistent display. Since different feeds use different formats, the date display looked awful
  • Worse, feed data is saved to disk in VW binary serialized form. Now I (and anyone else) using the latest dev build had a bunch of strings where I wanted timestamps

So what to do? Well, in VW there's a neat feature for serialized objects - schema migration. Say I have a class that looks like this:

Smalltalk.RSS defineClass: #RSSItem
	superclass: #{RSS.RSSAbstractTextObject}
	indexedType: #none
	private: false
	instanceVariableNames: 'read guid commentAPIUrl descriptionModule contentModule commentModule category pubDateString '
	classInstanceVariableNames: ''
	imports: ''
	category: 'RSSViewer'

Now, let's say that the objects stored on disk don't have the last item - pubDateString - because I just added that. No problem. Implement as a class method something like this:

binaryRepresentationVersion
	"for managing schema migration"

	^'1.0'

The previous version (the one on disk) will have a nil version. Now, add this method:

binaryReaderBlockForVersion: oldVersion format: oldFormat
	" An attempt is being made to read instances of
	an obsolete version of this class.  Answer a block
	that converts old instances (represented as an array
	or string of instance variable values) to new ones."

	oldVersion == nil
		ifTrue: [^self nilBinaryMigrationBlock].

Now, whenever you use BOSS to bring in serialized objects, the objects come in and get sent through this code to check for schema migration. The next question is, how do you implement the code that does the actual migration?

Here's how you do that:

nilBinaryMigrationBlock
	| inst |
	inst := self basicNew.
	^[:oldObj | 
	| newObj size |
	size := oldObj size + 1.
	newObj := Array new: sz.
	newObj 
		replaceFrom: 1
		to: size - 1
		with: oldObj
		startingAt: 1.
	oldObj become: newObj.
	oldObj changeClassToThatOf: inst].

We grab the old object in the form on disk, get the old values, and stuff them into a new instance. We then use reflection to transform the old object into the new object. Now, recall my initial problem - I had objects on disk of the same size (i.e., number of instance variables) as the new one, but needed to go from string to timestamp. Now problem. At the very end of the block, I added a message send to a new method: #stringToTimestamp: that did the conversion.

This is a very powerful technique, and one I've used a lot - not so much the data conversion as the shape change. This blog, for instance, started back in June 2002. My blog entry objects are actually saved not to a database, but to date stamped binary files. I've been modifying the blog code continually over that time period, and have added things like categories, trackbacks, etc. I've done all of that with schema migration, as above. The nice thing about this is that I don't have to read in all the files and do a conversion - they can happily stay on disk in their old format, and only get converted when (or if!) they get read in (for instance, as the result of a search). BOSS may be an old part of VW, but it's a very useful part, with a lot of neat features.

 Share Tweet This

smalltalk

Experts say Smalltalk is better

May 16, 2003 8:46:27.684

I spotted this in comp.lang.smalltalk. The link is to the original post - Niall Ross answers:

One can make the point that this is the only data there is. Noone has published any data telling a contrary story (that I know of). Making a decision based on scanty evidence is wiser that making a decision against what little evidence there is.

Lacking more data, one can sometimes use big name quotes, e.g.

  • Kent Beck (Mr XP) said (at ESUG 1999 in Ghent) that, "I program at a third of my Smalltalk speed in Java."
  • Bran Selic (RealTime UML guru, built the tool that is now the RT part of Rational Rose) said (at UML 2000 in York) that, "I was sorry to see Smalltalk lose out to Java because Smalltalk was the only language in which I noticed a real difference in my productivity".

As both these people make money from selling books that Java programmers buy, providing tools that Java programmers use and attending conferences that Java programmers go to, they have no commercial motive for the above remarks.

Of course, if your manager's reaction to the name 'Kent Beck' is to say, "Who?", then this won't achieve much.

the Gartner Group numbers are for initial Java projects, where the lack of experience is the major risk, and you will face (to a lesser extent - because Smalltalk is simpler than Java) a similar risk when doing your first Smalltalk Project

Quotes from people saying that Smalltalk is the ideal language for teaching and learning OO can be found easily and might address any management concerns. Be sure to get a couple of good books and a Smalltalk-aware coach to make the initial change.

Good stuff.

 Share Tweet This

development

Why closures are useful

May 16, 2003 8:31:01.985

Via the Fishbowl we get an explanation of why closures are useful, and why you won't see them in Java:

The advantage of closures is that they allow you to add new control structures to your language. Java 1.5 is looking to introduce a foreach construct to iterate over lists. With closures, such language constructs become unnecessary (Ruby has only very primitive native looping constructs) because you can define your own. Similarly, closures allow you to dispense with boiler-plate wrapping code such as we see everywhere with file or database manipulation in Java.

That's part of the reason Smalltalk is so much more productive than Java - mor expressive power. Why won't you see it in Java? Charles explains:

You can approximate the functionality of closures in Java using anonymous inner classes. There are two problems with this, though. Firstly, anonymous inner classes are unnecessarily verbose. Closures are supposed to be a short-cut, and anonymous inner-classes are anything but. This can be got around by adding some syntactic sugar to the language of course, but the use of classes is still quite heavy-weight. (Each anonymous inner class is an additional compilation unit, for example)

The bigger problem is that anonymous inner classes in Java don't really close over their surrounding scope - they cheat. The best way to demonstrate this by example is this:

i = 1;
1.upto(100) { |num| i *= num; }
puts i;

The above code prints out the factorial of 100. As you can see, the variable i is modified inside the closure, but because the closure is executed in the surrounding scope, its value is changed afterwards. This is unlike the behaviour of a regular function call, where variable values in surrounding scopes are not changed.

If you tried to write the equivalent code in Java, it wouldn't compile. Java doesn't really close over the surrounding scope, it copies it. To hide this implementation detail, any variable referenced inside the inner class must be declared final outside it: which is fine if your inner class is manipulating a mutable reference type like a list, but breaks if you want to work with immutable reference types, or value types. (i.e. Strings and numbers)

This is why you're unlikely to see closures in Java, sadly. To implement them properly would involve making changes to some pretty fundamental parts of the JVM. It's a pity, though, because they're damn useful

It's a pretty good read - gives examples in Ruby, which is explicitly modeled on Smalltalk.

 Share Tweet This

BottomFeeder

Updated the DEV parcel for Bf

May 15, 2003 21:30:45.068

A couple of days ago I posted a dev parcel for BottomFeeder that did not read in the 2.9 format feed file - which was a problem. Turns out I messed up the schema migration block when I was doing the module support. That's fixed, so if you try the dev build now, everything should be ok.

 Share Tweet This

movies

Matrix Reloaded - better than I expected

May 15, 2003 18:46:50.408

After seeing a few bloggers report in on Matrix Reloaded, I had low expectations for it - but it was pretty good. The pace was fast, the effects good. Some of the lines fell flat, but hey - you aren't watching it for plot, right? A good movie, not a great movie. Worth a trip, not worth multiple trips, IMHO.

 Share Tweet This

events

Smalltalk Solutions - Come this July!

May 15, 2003 17:44:51.170

There will be a nicer announcement forthcoming, but Smalltalk Solutions 2003 is going forward - July 14-16. Go visit the site and register - what are you waiting for?

 Share Tweet This

rss

About that dynamic RSS

May 15, 2003 12:02:06.917

Later today I'll be changing the dynamic servlet - I'll have it check the http headers for the relevant 'last-modified' information, and send along just the newer stuff. That should work with decent aggregators. Like, say, BottomFeeder.....

 Share Tweet This

movies

Off to see Matrix Reloaded

May 15, 2003 11:33:01.725

The early reviews sound disappointing, so my expectations are low....

 Share Tweet This

development

Grady Booch on languages

May 15, 2003 8:33:00.252

Here's an obvious headline for Booch: Language Once Was Key - Now It's Design. Heh, almost as much of a shock to see the UML guy pushing design to the front as it is to see me pushing Smalltalk to the front :)

Here's the link to the story. The basic claim is that .NET and web services obliterates the importance of any particular language - since all can play equally - and elevates design. Go have a look and see what you think.

 Share Tweet This

rss

So not getting the concept...

May 15, 2003 8:20:15.183

Via the .NET Guy's comment feed comes this beauty;

What people should do is use aggregators that don't go polling each and every hour for new content, but that collect the feeds when you are going to read them and hit the refresh button; like Aggie does, for example.

I guess many people here will leave their computers on at night, and with the session locked out. This means a bunch of refreshes (and consequently, bandwidth) that go unused :(

What's the purpose of automatic refreshing? Do you interrupt your work when you see there is new content awaiting, or just browse blogs while taking a break? Or perhaps is me, who mostly finds new content awaiting by the morning (living in Europe and mostly reading US-based bloggers...) and thus sees no point in auto-polling each hour. I guess there are many behavioural patterns with regard to blog reading... someone should write a paper about it.

sheesh. Replace RSS Reader with email client - should we get rid of periodic polling in those as well? See, I work during the day, and like to periodically see if there's new mail or new news without having to add an extra step. My reader uses conditional-get, supports gzip encoding, and also respects the update frequency tag (if in use) in RSS - both ttl and the newer ones in one of the modules. Which means that it's pretty light on the polling side.

 Share Tweet This

development

Type checking adds security?

May 15, 2003 8:13:51.984

Via Lambda the Ultimate - Here's a reality check on static typing as security:

We present an experimental study showing that soft memory errors can lead to serious security vulnerabilities in Java and .NET virtual machines, or in any system that relies on type-checking of untrusted programs as a protection mechanism. Our attack works by sending to the JVM a Java program that is designed so that almost any memory error in its address space will allow it to take control of the JVM. All conventional Java and .NET virtual machines are vulnerable to this attack. The technique of the attack is broadly applicable against other language-based security schemes such as proof-carrying code.

So much for that theory....

 Share Tweet This

movies

It's another geek holiday

May 15, 2003 1:12:28.110

With Matrix Reloaded out tomorrow, what else could it be?

 Share Tweet This

blog

Ok, I had to do it...

May 15, 2003 0:41:23.302

I added an incremental feed. The server keeps track of when you last queried, and only answers with new content since then (if any). Some of the proposals I've seen floated for this rely on client-tool help with cookies, or something in the feed. This solution does not rely on the client at all.

 Share Tweet This

rss

A little experiment...

May 15, 2003 0:03:08.358

I was looking at the .NET guy's blog and saw that he's a little worried about bandwidth based on RSS requests. I got pointed to this by Michael Lucas-Smith (one of the TypeLess guys), and he said I ought to write something in the way of a dynamic feed. Here's the issue:

Simon Fell remarked that he's concerned about the bandwidth from RSS on his site. His site supports HTTP caching properly, so it's probably not that big a concern.

One very prolific blogger (no need to name him, since it isn't his fault) is using a tool that does not supporting HTTP caching properly. Right now, his RSS feed is 302K. Think about that: 302K x once an hour = 7.1 megabytes per day, per subscriber. Have one thousand subscribers? 7 gigs a day. And you know what? What this person says is too valuable for me not to subscribe to his feed.

Yeah, I'd say bandwidth is an issue for some people.

This sort of implies that, sooner of later, we're going to need to leave static RSS behind and support dynamic RSS -- perhaps even a push variant for some people (although with HTTP caching, what you're saving there is a bunch of connections, not any significant bandwidth, until you're really up into the big leagues).

So, instead of bickering about XHTML in RSS, how about we hammer out a new syndication system that's a little more dynamic, so that we only get the new posts when there are some, and not get any data at all when nothing is new?

I'm less worried than the .NET guy; then again, he's likely using IIS, while I'm using Apache. I'm also using Smalltalk, so even though I don't care that much, I whipped a servlet up in between watching tv shows this evening. The servlet keeps a cache of IP addresses and the relevant (latest) item grabbed from them. On each request, it only answers things newer than the last request. I'll get around to deploying it tomorrow; it's late, and I'm tired....

 Share Tweet This

development

SQL Server and Dynamic Queries?

May 14, 2003 19:40:38.404

Over on the .NET guy's blog, there's some interesting information on SQL Server and Stored Procedures:

Frans Bouma publishes data that some people find very surprising, namely that his testing showed there was no performance advantage to stored procs in his case. I didn't find this surprising at all.

There's a general performance improvement that went into SQL Server 2000 (I believe) w/ regards to dynamic queries: that is, if you use parameterized queries, SQL Server can plot an execution plan for the parameterized query and cache it, and then next time that query comes through, use the already stored execution plan (despite the data being different). That basically kills the performance argument, because the advantage of a pre-calculated execution plan is eliminated. (In fact, it seems that I remember reading that sprocs in SQL2K weren't even stored in compiled form; rather a new execution plan is created and cached the first time it's executed, but I could be wrong on that.)

Now that's interesting. I'll have to take a closer look at the benchmarks, but that sounds very interesting. If that holds up, it should make O/R mapping simpler. Along those lines, the next thing in that post:

Now take this to the next step, as Paul Wilson does in Frans' comment area. Why not an O/R mapper? I have a strong feeling that Yukon will prominently feature the framework for treating SQL Server as though it were an object database.

We've taken it one step farther than an O/R mapper in our product, as the database stores very little in the way of relations (only the many-to-many mappings for query purposes). Objects are stored opaquely in the database and rehydrated dynamically as needed. But that's a story for another day. :)

Fascinating. Is Oracle doing anything like this, or IBM? Does this hold up for complex databases?

 Share Tweet This

general

Whoa - what's up with that?

May 14, 2003 19:23:41.142

Via Rob Fahrni - what's up with this? Follow that URL, and see if it opens your CD drive...

 Share Tweet This

smalltalk

Another blog where Smalltalk gets talked about

May 14, 2003 17:28:07.503

I check Feedster every so often to see what's being said about Smalltalk. Today that got me here, where I saw this and this. Here's an excerpt:

Recently I've been working on a small application which slurps a huuge dataset into memory, processes it for a bit and then writes some measurements out to disk. Now, it just so happens that I don't know exactly how to process the dataset to get the best results. Maybe I need to use an offset of 35. Or maybe it'd work better if I used 70. I don't know until I've tried a few values to see what works.

  Dataset dataset("input.dat");
  Answer answer = Process(dataset, 35);
  cout << "The answer is " << answer << "\n";

Reading the dataset into memory takes a good thirty seconds or so. So, I run it with "35" as the parameter. Ooh, that's really terrible. So, change it to "50", recompile, run the application. Wait another thirty seconds for it to reload the dataset. Zzzz, this is silly. Why do I need to reload the dataset each time?

This is the problem with C++. There are two seperate worlds. You start in the "source code world" which is inhabited by variables, type and comments. Then you pass through the Portal Of Compilation to reach the "executable world" which is inhabited by data, stack frames, and heap blocks. You're not allow back into "source code world" unless you throw all of your possesions into a big black hole, upon which they vanish forever,

Instead, I'd write a little bit of code which loads up the dataset, then switch into "executable world" and run it. Then I'd say "just wait there" to my stack frames and the heap while I nip back into "source code world" and write the next bit of code to process the dataset in some way. Then I'd return to "executable world" to run that code, see what the result is and then nip back to tweak my parameter. The "executable world" would always stick around, even though I'm changing the code.

Now, if you've only coded in C/C++ this will seem crazy. These language are a bit like a little wind-up car toy. You spend a while winding up your program, and then to run it you put it on a table and let it go .. and it goes "wheeee" and careers off in some random direction for a while until something goes wrong. So, you pick it up, wind it up some more, and try again. Wheeeeeee, it goes off in a slightly different direction to meet a different fate.

With smalltalk or lisp, you're not just a passive observer who watches as the car races off to its doom. You are actually sitting inside the toy car, keeping it on course. If the car drifts off to the left a bit, you just correct it and continue on your way. You don't have to go all the way back to the start.

That's as good a summary on the productivity benefits as you'll see. There's an RSS Feed for Andrew's blog as well

 Share Tweet This

BottomFeeder

Bf, Blog updates

May 14, 2003 14:57:08.311

I've been mucking about some more with modules - BottomFeeder now picks up item categories - whether organized under the category tag or under the dc:subject tag. I upgraded the blog feed to included categories, since the blog already has them. Additionally, I made sure to drop accurate item dates - I was dropping the file modification time, not the time of entry for each item.

 Share Tweet This

BottomFeeder

Updated DEV version of BottomFeeder

May 14, 2003 9:19:13.625

If you follow the dev versions of BottomFeeder, I have just posted an update to the main application. If you don't see it, change the upgradeURL line to read:

upgradeURL='http://www.cincomsmalltalk.com/BottomFeeder/upgrades/dev/'

After that, you should see the ongoing dev updates. I've started adding module support to the tool - look at feed properties for some of the new information (assuming that the feed you are looking at supports that information, of course). There's a module that gives error reporting information as well - so if you see a problem with a feed, and the feed's author has provided that information, you can send the information directly.

 Share Tweet This

development

What people hate about other programming languages

May 14, 2003 8:47:33.492

Via Dave Buck I spotted this argument in slashdot. As with most slashdot threads, this one meanders all over the place from a simple beginning:

"Perl programmers like punctuation. Python programmers like indentation. Every programming language has its own syntax, stemming from its philosophy. What I Hate About Your Programming Language examines the issues that shape languages as they grow. It's not advocacy, I promise."

So I had a look at the O'Reilly article that generated this little storm. It's an interesting piece that goes here:

Deciding a language is "good" or not is largely a matter of personal taste. I prefer dynamic typing and don't care much for the strong static typing found in C and its descendants. Part of that is personal taste - it feels like premature optimization to decide that a variable will always fit into eight or 16 bits. (Yes, I know judicious typedefs can lower some of the maintenance costs.) It's also practical; I don't write a lot of code that would benefit from static checking. (A buddy writes drivers at a semiconductor company. Static checking saves him time and effort.)

It's interesting to see just how many people are startingto show respect for dynamic typing - I think this is a large part of why there's a buzz around Python, for instance. It's no longer just us Smalltalk advocates - people who have used little (if any!) Smalltalk are coming to the same conclusions. Here's an interesting thought from that article:

Of course, choosing any one language for a project often means not choosing another language; sometimes that's the most compelling reason. I've had projects where a manager said, "We're going to use language X because that's what VCs expect us to use," where language X was, in my opinion, the wrong choice.

Going further, differences in language philosophy present a barrier to learning new languages. This doesn't just apply to existing programmers. It also applies to new programmers - learning to think like a programmer is difficult enough without bothering with syntax issues, editors, compilers, linkers, and distribution

There are way, way too many projects that went to Java for this reason, and I presume that many will go to C# for the same one. I wrote about the insanity of this kind of migration here. To sum it up, if you migrate from X to Y, what actual business value have you gained? The article gives some specific examples of the author's likes and dislikes; I like this example in particular:

It's often used inappropriately. Unless I'm writing a kernel, a device driver, a virtual machine, or an interface to a C or C++ library, writing in C is a probably premature optimization.

Now try explaining that to a long time C hacker though....

The summary is edifying as well:

Over time, my taste in languages has evolved. I used to worry about performance and variable-typing, but working with dynamic (or "agile") languages and learning to love test-driven development has biased me against strong-typing systems. Maybe learning a language like Haskell would balance my thoughts

Every language is sacred in the eyes of its zealots, but there's bound to be someone out there for whom the language just doesn't feel right. In the open source world, we're fortunate to be able to pick and choose from several high-quality and free and open languages to find what fits our minds the best

There's an interesting response to this article in the O'Reilly thread as well. The poster seems to know Squeak better than most Smalltalks, and conflates some of Squeak's issues with Smalltalk (Namespaces, for instance) - but it's got some good points:

What's not bad about Smalltalk

  • Speed. It's actually not that slow. Some tasks under Squeak are faster than Java. Java is faster for others. Cincom's commercial Smalltalk is faster than Java on just about everything.
  • multi-person development in an IMAGE based environment. FORTH programmers will known what I'm talking about. Classic Smalltalk stores the complete state of all objects in object memory in an IMAGE. This is basically one big database of objects. For a long time, the big deal with IMAGE based systems was that it was difficult to separate the development environment from the running application. Proper use of changesets and Projects seem to have done a great deal towards fixing this.

Of course, the commercial Smalltalk's all have good source code management support - varying from top notch stuff like Store (VW) and Envy (VA) to interfaces to more conventional (cvs style) systems. Furthermore, you can download just about any vendor Smalltalk implementation for free; check http://www.whysmalltalk.com for links.

 Share Tweet This

BottomFeeder

More module support

May 13, 2003 20:58:41.967

The syndication module is now supported in BottomFeeder. I haven't pushed an update yet - I'd like to do better testing before I do that. What does this add? Any RSS 1.0 or 2.0 feed that has publish frequency information in the syndication module will now have that respected.

 Share Tweet This

BottomFeeder

Basic Module support for BottomFeeder

May 13, 2003 18:37:45.742

I've added basic module support to BottomFeeder. What are modules? Elements that live in their own namespace so that collisions are avoided. The only one that is really used at present is the content module - see here for a description. Ironically, this is the tag that Bf needs least, since the VW XML Parser detects encoded content for me; I just look for this tag because feeds that use it probably don't have a description tag. I'll be adding support for additional modules as I have time - and - more importantly - starting to use some of the newly available information.

 Share Tweet This

tv

Penultimate Buffy

May 13, 2003 12:40:57.774

So we get to see Angel back on the last two episodes - what I'm waiting for is the Angel/Spike dialog - that has the potential to be very amusing. The other question - since this is it for the series, it's open season - Joss could kill pretty much any character at this point. So will any of the regulars end up pushing up daisys? Hmmm....

 Share Tweet This

java

The Emperor has very few clothes

May 13, 2003 12:31:26.273

I posted on the failure rates of J2EE and Java projects awhile ago. Now we have Jon Udell noticing the overselling of J2EE.

An oft-heard complaint, echoed recently by Annrai O'Toole, is that J2EE app servers are oversold:

The J2EE vendors have done a fantastic job of convincing the world that you can't run a line of Java unless it runs inside a J2EE container. This is just pure bunkum.

I like his formulation that "J2EE is the Java equivalent of a mainframe." We also have, of course, in COM+, the Windows version of the same idea, which in its earlier MTS incarnation predated J2EE. I also notice that the real mainframes haven't gone away. With respect to the middleware services for which the J2EE server is best known -- "TP-heavy" transaction management, connection and object pooling, role-based security, and declarative control of these aspects -- the question of when and why this stuff is or isn't overkill seems never to go away

Needless complexity.... There are times you need the heavyweight stuff. But most of the time, you don't

 Share Tweet This

itNews

Evolution and IT

May 13, 2003 11:56:33.413

Heh. In the IRC today, Alan Knight let this slip:

This comes back to my notion of evolutionary IT. It's a mistake to assume that there's any guiding intelligence in IT. Decisions are made at random. Over the course of millions of years, certain decisions will result in a greater survival percentage....

I guess we settle in for a long wait....

 Share Tweet This

news

Funny story from Texas

May 13, 2003 9:11:05.737

Regardless of your policy views, this is just amusing. There's one way to "filibuster" programs you object to :)

 Share Tweet This

smalltalk

Clarence asks, I answer :)

May 13, 2003 9:09:04.374

Clarence noticed that I pointed out a new Smalltalk aggregator, and asks

where's the code?

I don't know about the Squeak code, but the VW code for BottomFeeder is at SourceForge - although for up to date access, get a public Store account and grab the BottomFeeder bundle. You should also load the latest Twoflower bundle - the system will load the 'goodie' version from the parcel directories, but it's out of date relative to the database.

Anyone interested in the code that powers this blog can grab the CST-Blog bundle from the public store as well.

 Share Tweet This

smalltalk

Smalltalker aficionado blog

May 13, 2003 8:53:55.335

I should point out (as I did here tangentially) that Douglas has a blog. He's got a fair bit of Smalltalk content (using Squeak) - check it out.

 Share Tweet This

rss

Another Smalltalk aggregator

May 13, 2003 8:33:17.292

via Chris Double comes news of a Squeak based aggregator. Welcome to the fray!

 Share Tweet This

java

More Java silliness in upper management

May 13, 2003 0:02:08.072

Got this one in email today - along the same lines as this and this:

Things are going okay for now, but it's getting more and more difficult to convince anyone to do anything in Smalltalk. I can't understand how a company that is finally reaping benefits of a large-scale project done in Smalltalk (successfully), starts looking to throw all that investment out of the window and go with a lesser tool.

In my particular area, we deal with both Smalltalk and Java, and we (Smalltalk team)are consistently delivering a more stable product faster (which means that we usually 'wait' until the Java part is ready). My team lead sees that, my manager sees that, even my director sees that. But when it comes to the VP, it's all Java talk.

Here's a tip for IT managers everywhere: If it's not broken, don't fix it. Maybe, just maybe, the company you work for won't have to lay off half your staff if you keep that in mind....

 Share Tweet This

development

More details on that development story

May 12, 2003 21:38:43.619

I received more details in email from the guy who sent me this:

I forgot to tell you the really fun part. (dohh!) Yes, part of the problem was mismanagement. A bigger problem was C++ and what Rhapsody could and could not do with it. The guys ended up doing some pretty basic R&D on the Rhapsody codebase which we guilt-tripped out of the vendor. This product gives great demo, but doesn't deliver for complex tasks. And of course one could replicate it in Smalltalk in about a week and not pay the ridiculous fees.

One of the biggest problems was building a decent message passing system between CPUs. As the doors are closing, there are still rancorous arguments about CORBA vs. RPC vs. sockets, and all of them are ugly in one way or another. C++'s lack of reflective capability is simply a disaster, and our C++ jocks could barely comprehend the nature of the problem.

Dohh! again....

 Share Tweet This

cst

New VW 7.1 engines available

May 12, 2003 21:35:25.397

VisualWorks developers - there are new VW 7.1 engines available for download:

These 7.1a engines are the most up-to-date engines for VisualWorks 7.x imagesas of May 2003. Version 7.1 engines are backward-compatible with 7.0 images and are recommended.

The version 7.1a engines fix the following bugs in the 7.1 engines:

All Platforms

  • The primitives for longLongAt:put: and unsignedLongLongAt:put: are broken for large integer values.
Linkable GUI Platforms (AOSF, Linux86, LinuxPPC, LinuxSPARC, Solaris)
  • The linkable GUI platforms could not do international input.

These problems have been addressed; download links for all engines are available here

 Share Tweet This

development

Woulda, Shoulda, Coulda......

May 12, 2003 18:08:54.623

I got this in email from a former colleague trapped in the unproductive bowels of the Java-Verse:

Thought I'd add another entry to your probably-overflowing file of "Gee, they shoulda used Smalltalk" stories.

For the last three years, I've been working on the UI for an industrial robot as a contractor for a guy I had worked for before. I tried to sell them Smalltalk but they went for Java, which worked thanks to the use of Smalltalk techniques but still didn't meet their realtime requirements. Eventually we switched over to Qt and life got really unpleasant. But that's just a side story.

This project has been running for several years. My client originally sold this project to a Japanese company that has trouble writing software. He sold it based on a software tool called Rhapsody: draw a bunch of UML diagrams and it generates C++ for you. His client saw this and went wild.

The last three years have been an interesting roller-coaster ride, consisting mostly of the inability of a *very* strong team to create the necessary software in a reasonable amount of time. Part of the problem was mismanagement, or simply lack of management, which is odd because the guy who started this has a reputation as the ultimate software development manager.

Recently, his client sent over a Japanese OO expert to take a look at what was going on. There was a big company pizza party to introduce him. He gave a little speech in which he said there was this system that he had first used back in 1984 and it still amazed him that everyone wasn't using it.

I was told by others present at a high-level meeting that my client asked this OO guy how he would have approached this problem. He said he probably would have started off writing it in Smalltalk.

BTW my client's company is closing its doors this Thursday.

Dohh!

 Share Tweet This

cst

Two memory system posts this weekend

May 12, 2003 10:21:55.108

I made two posts this last weekend that are now pretty far down the scrolling list of posts - if MemoryPolicy and ObjectMemory interest you, have a look:

 Share Tweet This

development

OO - panacea, or otherwise?

May 12, 2003 10:11:49.089

I've certainly never thought of OO as a silver bullet - it's a useful technique for solving software problems, nothing more. The enemies of OO certainly like to paint it that way though. There's so much unclear on the concept stuff on that page that it's hard to know where to start; here's a sample of how this guy goes off the rails:

Let me give an example of this. Suppose I want to define a ubiquitous data structure. ubiquitous data type is a data type that occurs "all over the place" in a system.

As lisp programmers have know for a long time it is better to have a smallish number of ubiquitous data types and a large number of small functions that work on them, than to have a large number of data types and a small number of functions that work on them.

A ubiquitous data structure is something like a linked list, or an array or a hash table or a more advanced object like a time or date or filename.

In an OOPL I have to choose some base object in which I will define the ubiquitous data structure, all other objects that want to use this data structure must inherit this object. Suppose now I want to create some "time" object, where does this belong and in which object...

This gets a big huh??? - even in statically typed monstrosities like Java, interfaces allow one to define objects where they belong, but create a consistent interface. Smalltalk has always allowed for this, as had CLOS. Coming from someone who seems to know Lisp, I'm just baffled. This is either a straw man argument, or a real failure to grasp the concept. There's more; go see for yourself

 Share Tweet This

development

.NET Blogs keep multiplying

May 12, 2003 10:05:06.594

Microsoft seems to understand that blogs are a fine way to get information out, and encourages their people to do so. I just found this one via Lambda - which covers implementation details on the .NET CLR. RSS feed here

 Share Tweet This

development

Power Programmers redux

May 12, 2003 8:14:42.065

I posted on a CIO Insight article recently - the one thatwentinto John Parkinson's theories on who actually does most of the development work. Today, Terry Raymond points out that the ACM has noticed the artcle as well:

John Parkinson of Cap Gemini Ernst & Young concludes that, as far back as the late 1970s, the most sophisticated and reliable software applications were chiefly the work of a small portion of programmers who were labeled 10X or Power Programmers, but these individuals fell out of favor when companies started concentrating on boosting the performance of average programmers via tools and methodologies. However, Parkinson has found indications that Power Programmers are staging a comeback, as evidenced by software products such as Squeak, an advanced version of the Smalltalk object-oriented development environment, and the inSORS Grid IP Multicast collaboration and videoconferencing system.

Interesting how people are noticing high levels of productivity and Smalltalk simultaneously. Now if they could just connect the dots.....

 Share Tweet This

tv

Yes! Someone else likes "Firefly" better!

May 12, 2003 0:35:49.173

This rundown on Startrek was just perfect. This is funny:

Yeah, I know this one is overdone, but you'd think that the first time an explosion caused the guy at the nav station to fly over the captain's head with a good 8 feet of clearance, someone would say, "You know, we might think of inventing some furutistic restraining device to prevent that from happening." So of course, they did make something like that for the second Enterprise (the first one blew up due to poor lubrication), but what was it? A hard plastic thing that's locked over your thighs. Oh, I'll bet THAT feels good in the corners. "Hey look! The leg-bars worked as advertised! There goes Kirk's torso!"
Here's the "Firefly" reference:

Star Trek:

Picard: "Arm photon torpedoes!" Riker: "Captain! Are you sure that's wise?" Troi: "Captain! I'm picking up conflicting feelings about this! And, it appears that you're a 'fraidy cat." Wesley: "Captain, I'm just an annoying punk, but I thought I should say something." Worf: "Captain, can I push the button? This is giving me a big Klingon warrior chubby." Giordi: "Captain, I think we should reverse the polarity on them first." Picard: "I'm so confused. I'm going to go to my stateroom and look pensive."

Firefly:

Captain: "Let's shoot them." Crewman: "Are you sure that's wise?" Captain: "Do you know what the chain of command is? It's the chain I'll BEAT YOU WITH until you realize who's in command." Crewman: "Aye Aye, sir!"

heh. Go read the whole thing

 Share Tweet This

management

Bob Lewis on measuring time usage

May 11, 2003 18:27:11.044

Bob Lewis has a good commentary out on IT management's tendency to want to measure everything:

Someone - probably Deming - once said that if you can't measure you can't manage. Or, if you can't measure you can't improve. Something like that.

The problem is that instead of keeping the thought in context, managers, egged on by an army of consultants, immediately applied it to every blessed thing in the business without thinking very hard about the implications.

Many have missed the most important impact of measurement, which is that once you institute a program of formal measurement, you get what you measure and only what you measure.

That last part ought to be in bold: once you institute a program of formal measurement, you get what you measure and only what you measure

 Share Tweet This

news

This is, well, odd...

May 11, 2003 12:32:30.241

Klingon???

PORTLAND, Oregon (AP) -- Position Available: Interpreter, must be fluent in Klingon.

"There are some cases where we've had mental health patients where this was all they would speak," said the county's purchasing administrator, Franna Hathaway.

County officials said that obligates them to respond with a Klingon-English interpreter, putting the language of starship Enterprise officer Worf and other Klingon characters on a par with common languages such as Russian and Vietnamese, and less common tongues including Dari and Tongan

 Share Tweet This

examples

More on VW Memory

May 10, 2003 14:27:42.598

I wrote about VW memory management here the other day. In that article, I mostly went over areas you can change by implementing a custom Memory Policy class. That's hardly the only thing you can do though; there are a variety of settings in class ObjectMemory that you should be aware of. An excellent place to start is the documentation protocol on the class side of ObjectMemory - look at spaceDescriptions and reclamationFacilities - these two methods are actually doc. After you've read that, you'll have a better handle on how the VW memory system works.

For most applications, there are two memory spaces you'll want to take note of:

  • New Space (Eden)
  • Old Space

In rough terms, New Space is where objects are born. Old Space is where objects that don't die immediately go to live. If you think about it, it's clear why these two areas are of interest - if New Space is too small, then objects get tenured off into old space too quickly - and depending on how you have set up growth policies (see my earlier post), you can get either rapid memory growth or thrashing - or both in sequence. On the other hand, makeit too big, and the incremental collector - the one that scans New Space on a regular basis - may well spend too much time doing so, making for slower performance. The "correct" size is a balance between processor speed and application behavior - so you'll have to test it out. The default setting is often ok as-is.

Then there's Old Spacee - objects that don't get wiped out by the incremental collector go here to live - and remember, Old Space is not going to get scanned unless:

  • The result of #favorGrowthOverReclamation is false, and the system has to scavenge to create space for objects moving from New Space
  • You manually invoke the garbage collector (for instance, using the launcher menu)

If you know that your application creates lots of long lived objects, it's a good idea to increase the size of Old Space up front. Recall that MemoryPolicy merely controls how thesystem behaves - not how much space is available at startup. To change the space sizes, you can do one of two things:

  • Use ObjectMemory class>>sizesAtStartup: to tell the system to increase the starting sizes at system startup. If you send this message, make sure to save the image - this only happens at startup!
  • Use the API for expanding memory - ObjectMemory class>>growMemoryBy:

You can also shrink memory - but you want to be careful about doing that. In general, you should let the system do that itself via the settings in MemoryPolicy.

This barely scratches the surface of things you can do with the VW memory system - the settings allow for a lot of control over how and why memory is expanded or contracted. Make sure you read the class comments in MemoryPolicy and ObjectMemory - and the documentation methods there - before you get started. Questions? Send them my way

 Share Tweet This

development

Macros (Lisp) and Keywords + Blocks (Smalltalk)

May 10, 2003 12:06:05.904

Patrick Logan points out that with keyword messages and blocks, you get an awful lot of the goodness of macros in Lisp:

While Smalltalk doesn't have syntax macros like Lisp, Smalltalk *does* have simpler block syntax and keyword arguments.

The effect is that new keyword messages can take block closures, which essentially delay evaluation until the method behind the message decides to evaluate them, and the message send looks an awful lot like new syntax, very clean.

Many uses of macros in Lisp, frankly, are simply created to hide the appearance of the lambda keyword. Of course there are more "legitimate" uses of macros, but these are less common.

This was noticed by Ted Leung, who asked:

This use of keyword messages and closures is really interesting. In Chapter 8 of On Lisp, Graham lists 6 reasons to use macros. Delaying or altering evaluation is an aspect of the first 4 reasons. Reason 5 involves using the calling environment, which you very rarely want to do, reason 6 involves using a new lexical environment, which you also rarely want to do, and reason 7 is inlining which is a performance annotation.

I'd be curious to see some examples of this type of Smalltalk code.

Rich Demers tried to answer on Ted's blog,but ran into a small problem with BottomFeeder's implementation of the CommentAPI - I was url encoding the text. Dohh! I fixed that, but here's the link Rich was pointing to

 Share Tweet This
-->