You have to love what Sun is doing to Ted Neward. He's been a pretty tireless advocate of Java over the years, and Sun is after him (and gosh knows who else) for trademark infringement. Someone needs to beat these people with a cluestick :)
I have no idea who the wiki spammer is, but here are some of the slimy companies that he promotes - all I can say is, avoid doing business with these clowns - they advertise via spam:
- http://www.online-ccc.com/ - some kind of international consulting firm out of China. I suggest avoiding them.
- http://www.bochao.com.cn/cad.htm - some kind of software company, selling CAD stuff. Slime
- http://www.antu.com.cn/fme_jjie.htm - looks like a consulting firm. Again, slime - avoid them like the plague.
There you go losers - hope you enjoy the publicity. So long, and I hope you go out of business.
Next time you worry about the fact that your code has insufficient levels of comments, read this from Bob Congdon. It may not fix anything, but at least you'll know that you have plenty of company out there :)
I've been twiddling with the scraping plugin this weekend and this morning - I'm not ready to release it yet, since it's a bit "rough" around the edges. I thought I'd post another example of a scraping script - this one more complicated. I'm something of a political junkie, so I enjoy reading sites like Tapped and The Corner. As it happens, Tapped has a feed, but the Corner doesn't. The script for scraping that to a local RSS file is more involved than the one I posted the other day:
| writer content str rest out contentBlock today yesterday itemBlock todayString yesterdayString| authorBlock := [:chunk | | authorStream all | authorStream := chunk readStream. all := authorStream through: $>. authorStream atEnd ifTrue: [all copyWithout: $]] ifFalse: [authorStream upTo: $<]]. itemBlock := [:builder :chunk | | itemContent time timestamp itemStream descStream author lnk| itemStream := chunk readStream. itemStream through: $". itemStream throughAll: '<b>'. builder title: (itemStream upTo: $<). itemStream through: $[. author := authorBlock value: (itemStream upTo: $]). builder author: author. itemContent := itemStream upToAll: ''. descStream := WriteStream on: (String new: 1000). descStream nextPutAll: '<p><b>Posted by: ', author, '</b></p>'. descStream nextPutAll: ((itemContent trimBlanks) copyWithout: Character lf). builder description: descStream contents. itemStream throughAll: 'Posted at'. itemStream through: $". lnk := (itemStream upTo: $") trimBlanks. builder link: lnk. itemStream through: $>. time := [Time readFrom: (itemStream upTo: $<) readStream] on: Error do: [:ex | Time now]. timestamp := Timestamp fromDate: Date today andTime: time. builder pubDate: timestamp]. contentBlock := [:builder :chunk | | stream | stream := ReadStream on: chunk. [stream atEnd] whileFalse: [ | itemChunk | builder startItem. itemChunk := stream throughAll: '<a name'. itemBlock value: builder value: itemChunk. builder endItem]]. out := 'nro.xml' asFilename writeStream. writer := RSSSax.RSS20_SAXWriter new output: out. writer prolog. writer startRSS. writer startChannel. writer title: 'NRO Corner Feed'. writer link: 'http://www.nationalreview.com/thecorner/corner.asp'. writer description: 'NRO Corner Feed'. writer pubDate: Timestamp now. content := 'http://www.nationalreview.com/thecorner/corner.asp' asURI valueStream contents. str := content readStream. today := Date today. yesterday := today subtractDays: 1. todayString := today monthName asString, ' ', today dayOfMonth printString. yesterdayString := yesterday monthName asString, ' ', yesterday dayOfMonth printString. str throughAll: todayString. str throughAll: '<a name'. rest := str upToAll: yesterdayString. contentBlock value: writer value: rest. writer endChannel. writer endRSS. out close.
The interesting thing about this is how it looks more like procedural code with functions than it does like OO code. I could define classes and then execute methods in them, but that starts getting verbose in a script. Instead, I defined three blocks that handle the complex parts of the parsing (stripping email hrefs in the author block, for instance). The upshot of all this is that I ended up with a nice feed, with full content. The Tapped feed is one of those partial content deals; I may end up creating a script that scrapes that as well.
Once I get the script tool a little more polished, I'll push it out as a normal update. If you would like to play with it now, it's in the public store, bundle RSSScriptRunner
Hacking a website isn't something I support - but I've got to admit, the SCO Page is amusing this morning. Look at what the woman in the background is writing, for instance. If they've fixed the site by the time you read this, I saved a copy of the image here. It's in place of the "webinar" banner image.
This spoiled my breakfast, so I felt compelled to share. Here's a story about a soda company desperately in need of a cluestick. I mean really - mashed potato flavored soda? Gah...
Jones Soda Co. takes the idea of a liquid diet to a new low. How does Green Bean Casserole Soda strike you? And how about an aggressively buttery-smelling Mashed Potato Soda?
Even the creators of the fizzy concoctions at this small Seattle soda company can hardly stomach the stuff. But last year's unexpected success of the Turkey & Gravy Soda means another round of bizarre food-flavored soft drinks. As an added bonus they're calorie-free.
This week Jones Soda Co. launches a full meal deal of five Thanksgiving soda flavors, from the bile-colored Green Bean Casserole to the sweet but slightly sickly Fruitcake Soda. Last year's Turkey & Gravy is also back on the menu.
I have to agree with Tim Bray here - the benefits of corporate blogging far, far outweigh any negatives you might think of. I've been running the Cincom Smalltalk blogs for over 2 years now; the community of bloggers has grown, and we're getting a lot of positive notice - notice that I don't think we could have gotten any other way. Here's how Tim puts it:
Despite all that, [corporate blogging obstacles] I think this is going to start happening, and the reasons are obvious. Today, in late 2004, there are exactly two companies in the world where blogging has gone wide-open: Sun and Microsoft. At both places, the impact has been overwhelmingly positive. Neither of us would consider going back for a second.
The existence of the Sun and Microsoft blogs is, every day, making our competitors' lives a little harder. This kind of competitive advantage generally just doesn't go unanswered; we are after all living in a free-enterprise system.
Most CEOs, and all good CEOs, are very outward-facing. They see what's going on, and they don't sit tight and let competitors maintain a competitive advantage. Especially when setting up enterprise blogging is easy and cheap.
If you've downloaded a dev build of BottomFeeder recently, you'll want to replace it - just grab the appropriate one of these three files:
Just replace the file you have in the install with the one you downloaded and restart. You can also delete any files sitting in the 'app' directory. Why do you need this? There was a problem with the loader that prevented any updates from loading. That's fixed now, but you need the new build.
I've taken to reading about the first world war lately - my grandfather (mother's side) fought in it after having come to America from Sweden. I recommend this one on the immediate background to the war - Europe's Last Summer. It focuses on the summer leading up to the war, when no one in Europe expected anything to happen. It's a fascinating look at how the continent slid into a catastrophic war. I read that last summer - right now, I'm reading two books that qualify as "oral history" of the war: Eleventh Month, Eleventh Hour, Eleventh Day - it's a view on the end of the war through the eyes of people who were there. It traces back through a number of people's war experience, ending with how they got through (or didn't get through) that last day. Amazingly enough, the allies were launching attacks right through 10:30 AM that day - my grandfather was nearly sent on a suicidal attack that morning himself. Finally, I'm also reading Forgotten Voices of the Great War. It comes out of a British project started in 1972, where recollections of veterans were recorded. It's truly fascinating, from the near ecstasy some of them felt when the war started, straight on to their disillusionment and horror at the front later on. You'll need a strong stomach to read this last book; a lot of the recollections are very, very raw.
I can't pretend that these books give me anything more than a (very) vicarious understanding of what my grandfather experienced, but it's interesting nevertheless. The first world war is the tragedy that created the rest of the 20th century - and the echos are still reverberating through our world now.
There's only 1 week left to register for the Cincom Smalltalk Worldwide User's Conference in Frankfurt, Germany. Have a look at the agenda - there are PDF versions available for download - English here, German here, and French here.
One of the things I get asked about a lot is how VisualWorks developers should proceed with GUI plans - Pollock is coming (usable beta next year, full support in 2006) - see the roadmap. I realize that full production on this is a ways out, and that our user community has real work to do in the meantime. Here are a few tips on how to proceed:
- Read Sames' blog. Sames is posting on Pollock development regularly - it's your best way to get information on what's happening - and your best way to provide early feedback
- Join vw-dev. This will give you early access to developing code, as well as access to our developer forum
- Use the current GUI tools - but prepare for the future:
- Separate your UI code from your domain logic
- Use trigger events instead of dependency. This is covered in the documentation
- If you customize the Cincom UI frameworks, make sure that you keep that code in a separate package that is easily identifiable
When Pollock ships in full production, we'll have migration tools available - and the more closely you've hewn to the UI steps outlined above, the easier it will be to migrate.
Awhile back Bob mentioned some scraping tools he created for use with BottomFeeder. I decided to have a look at them today, because I decided that I'd like to have a subscription to User Friendly. I loaded Bob's code (Simple Script Runner from the public Store) and had a look. I decided that it would be more useful if it had some SAX drivers attached, so I created a new bundle - RSSScriptRunner - that included a few. I'm planning to enhance this little package some, but in the meantime the following script produces a valid feed with today's User Friendly comic in my local Bf directory:
| writer content str rest out | contentBlock := [:builder :chunk | | stream | stream := ReadStream on: chunk. stream throughAll: 'SRC="'. builder link: (stream upTo: $"). builder title: 'User Friendly For: ', Date today printString. builder description: '<a href="', chunk. builder pubDate: Timestamp now]. out := 'userFriendly.xml' asFilename writeStream. writer := RSS20_SAXWriter new output: out. writer prolog. writer startRSS. writer startChannel. writer title: 'User Friendly Feed'. writer link: 'http://www.userfriendly.org/'. writer description: 'User Friendly Feed'. writer pubDate: Timestamp now. writer startItem. writer title: 'User Friendly For: ', Date today printString. content := 'http://www.userfriendly.org/' asURI valueStream contents. str := content readStream. str throughAll: 'CARTOON FOR'. str upToAll: 'href="'. rest := str throughAll: '</A>'. contentBlock value: writer value: rest. writer endItem. writer endChannel. writer endRSS. out close.
Works like a charm
Lambda the Ultimate links to another IDE post. This is another one of those areas where non-Smalltalkers and Smalltalkers tend to talk right past each other. If you are using Java, you can code in Eclipse, or IntelliJ - or Notepad. If you use Smalltalk, it's simply not like that. With Smalltalk, the IDE is the language for all intents and purposes. What you are doing as a Smalltalker is akin to the old saw about sculpting a statue - you remove everything that doesn't look like a statue, and then you're done. The dilemma pointed out in the linked article doesn't really exist for the Smalltalk developer (as noted in the comments at the end). Need something added to Smalltalk? Why go ahead - extend the language and/or the base classes.
I just discovered that I had about 10 old posts that had comment spam. These posts were ones that had been cross linked (like this one) and showed up in some relatively common Google searches. The reason I missed them was simple - they were all posts that had fallen out of my RSS feed, so I never noticed. The new spam filtering I've added should prevent this problem going forward; it's already nabbed one attempt to hit a post that had aged out of RSS.
Ben Hammersley notes that real estate agents are about to get disintermediated:
Real-estate agents have been on the endangered-profession list for a while (thanks, Internet and 2% brokers), but Home Depot may make them extinct. In seven southern states, the DIY store will be testing home-selling kits aimed at the growing for-sale-by-owner market. For $12.95, you get a sign to put in your yard, but more important, you get a listing and photos on Owners.com, which claims to be the largest for-sale-by-owner site, with 5 million customers. The site has an answering service that fields calls from prospective buyers, eliminating the rôle of agents and their 6% commissions. If the test goes over well, Home Depot plans to offer it nationally. And loud blazers will be seen only at country clubs.
Couldn't happen to a nicer bunch of value subtracting people...
We got Thanksgiving finished (I'm still stuffed from leftovers), bundled my parents off to Florida - and now we're off to my wife's 25th high school reunion. I need a nap.
Blogs as an embedded marketing mechanism? That's what's started up, according to PR Opinions:
"The bloggers will get $800 a month to mention Marqui with a link once a week in their blogs and post its emblem on a page. They'll get an additional $50 per qualified sales lead they send to Marqui....But transparency and integrity are the order of the day, King said. Information about Marqui's "Blogosphere Program" is posted on its corporate Web site, and bloggers are urged -- but not required -- to disclose the relationship."
You can see the details on the Marqui site. PR Opinions is worried as to whether the advertising will be up front or not; I rather suspect that Marqui hopes it will be like the Coke can that the TV character "just happens" to be drinking from. Looks like blog reading just got more complicated :)
I've got a solution on the blog that seems to be dealing with spam - I just discovered some attempted comment spam sitting in an archive folder - exactly where I expected to find it. I haven't had a serious issue with spam on this server anyway; I'm not running one of the well known blog systems like MT, so I don't attract as many attempts. Having a homebrew system seems to deter a lot all by itself, but the extra checks I've got in place seem to be catching the rest (so far).
It's a blustery Thanksgiving here, but we won't notice at all with the food we've got ready to go. Plenty of Turkey, stuffing, and other assorted goodies. Happy Thanksgiving to everyone!
Young people just aren't interested in reading newspapers and print magazines. In fact, according to Washington City Paper, The Washington Post organized a series of six focus groups in September to determine why the paper was having so much trouble attracting younger readers. You see, daily circulation, which had been holding firm at 770,000 subscribers for the last few years, fell more than 6 percent to about 720,100 by June 2004, with the paper losing 4,000 paying subscribers every month.
Imagine what higher-ups at the Post must have thought when focus-group participants declared they wouldn't accept a Washington Post subscription even if it were free. The main reason (and I'm not making this up): They didn't like the idea of old newspapers piling up in their houses.
Don't think for a minute that young people don't read. On the contrary, they do, many of them voraciously. But having grown up under the credo that information should be free, they see no reason to pay for news. Instead they access The Washington Post website or surf Google News, where they select from literally thousands of information sources. They receive RSS feeds on their PDAs or visit bloggers whose views mesh with their own. In short, they customize their news-gathering experience in a way a single paper publication could never do. And their hands never get dirty from newsprint.
I have news for the media - that rationale goes beyond young people. It's why I stopped subscribing to newspapers a decade ago. I can get the NYTimes, the Post (and lots of other papers free in my browser - with updates coming at BottomFeeder hourly. These numbers (pdf) can't be encouraging either:
The Post experience merely mirrors the results of a September study (.pdf) by the Online Publishers Association, which found that 18- to 34-year-olds are far more apt to log on to the internet (46 percent) than watch TV (35 percent), read a book (7 percent), turn on a radio (3 percent), read a newspaper (also 3 percent) or flip through a magazine (less than 1 percent).
This is going to be a wrenching change for the media, and - thus far - they seem to be in denial over it.
Scoble has hit on a key part of the disconnect between the entertainment industry (movies, tv, music) and the rest of us:
David told me that his friends in the movie business really don't like the long tail. They hate it, in fact. They hate that they can't manufacture a hit movie anymore with awesome marketing. They hate it that Steve Jobs, with Pixar, is kicking their behinds by making movies that people talk about in the word-of-mouth networks.
I see it in my aggregator. The Incredibles is STILL being talked about on blogs. Many of those blogs only have 10 to 100 readers. Maybe even less. But, that's where the profitability comes from. Every blogger that talks about a movie makes that movie more profitable.
I told David that blogs are only the tip of the iceberg. Blogs are only the part of the word-of-mouth networks that we can see. So, for every blog that talks about something, there are probably 100,000 conversations that we can't see. Blogs just give us a fuzzy picture of what really is being discussed person-to-person in IM, email, on the phone, or over turkey dinner tomorrow at Thanksgiving.
This actually explains a lot about the legal approach that they've taken to p2p. Instead of creating their own electronic markets (with price points that work), they have been trying to shut down the entire space - with intimidation suits and new law. What they want is complete control of the information channel, and they are in complete denial about the fact that it's impossible.
One of the tensions that comes between Product Management and engineering is component importation. The people who build infrastructure would (generally) prefer to do the work in-house. No, it's not all an NIH problem - there's a rational reason for it. You need look no further than the current version of VisualWorks to see what I'm talking about. We've imported a bunch of tools over the last few releases:
- The Refactoring Browser
- The Professional Debug Package
- The ICC ADvance Tools
Now, look at the various inconsistencies in the menus, keyboard shortcuts (etc.) between these tools and things we've built internally (like the new inspectors and the workspace). That's the downside of bringing in third party tools - there's a fair bit of adaptation to make them "fit" with everything else (not to mention underlying framework issues that might crop up). On the other hand, doing all the work internally isn't an answer either - you get marvelously consistent tools, but they appear a lot more slowly. As to resource constraints - it's never easy to "just hire enough people" to build tools. There are constraints in any business, and Cincom Smalltalk is no different from any other here - we have to live within our means, just like everyone else.
So where does that leave us? I'm making this post in part to ask the community. Importing tools from the community into the product (even free ones) adds functionality quickly, but at the cost of adding inconsistency to the tools (and adding back-end cleanup work to our team's queue). Not importing tools has a cost as well - the question is, which way do you, the end users of our products prefer?
Here's a way that you don't want to start the day before Thanksgiving - you know, the day when your plan is to do a lot of prep cooking. My wife was going to head off to the gym, so I had to fetch the clean laundry from the basement - that's where all the clean bathing suits were. That's when I found today's nasty homeowner problem - basement flooding.
It's been raining, but not too heavily - so my first thought was some kind of leak. That wasn't the case, and it was unlikely anyway - we had installed a fairly large scale drainage system two summers ago outside. When I walked past the washing machine, the problem became clear - it had been on "rinse" all night (specifically, the fill portion) - and water was pouring out. Turning it off stopped any further damage, but there was water all over. For extra fun, the sump pump is on the other end of the basement, and the floor near the laundry area slopes away from it.
The water was maybe a tenth of an inch deep in places, so a pump was out of the question - $45 later I had a shop-vac. I sucked up the water while Jackie looked at the washer - which wasn't broken (a good break there). The upshot is, we now have scads of damp clothes to wash, and a potential mold problem to deal with. Lovely way to slide into the holiday...
With the fall release almost in the bag, it's time to ask the community what's important to them. So, please fill out our latest survey and let us know what you think!
It turns out that you can not only change font definitions in VisualWorks, but you can save those definitions out to disk and reload them. I've added some basic support for that to the development upgrade path in BottomFeeder. After you grab the update, restart - there will be a new menu option under 'System' that allows you to define and save fonts. I'll be modifying that to allow newly defined font definitions to show up in the (short) list of defined fonts on the settings page, but I haven't gotten to that yet. Stay tuned. A few caveats - the underlying support in VisualWorks for this is not complete - on some platforms you won't see a full list of all available fonts.
The music industry has reached bizarro territory - killing its own young in the quest to ensure that all music fits into their box. Have a look at this from Joi Ito:
"I thought it was a new kind of fraud," said Naoki Kasugai, who runs Daytrip, a nightclub that offers live music in Nagoya. He received a letter from JASRAC in summer 2003 along with an invoice for a monthly charge of 28,350 yen in copyright fees, covering the entire time his bar has been open since 1997. It totaled a whopping 2.32 million yen.
Kasugai was shocked and puzzled. He had never heard from JASRAC before. He figured someone was trying to con him.
But after receiving a second invoice from JASRAC, he called to find out what was going on. A JASRAC official came by in person to explain: "The bands you hire have likely played covers of songs by other composers. We want you to pay the copyright fees on those songs."
"How many cover songs does this account for?" asked Kasugai.
"We don't know how many copyrighted songs were played here," the official replied. "So we are not charging for each of them. Instead, we are charging on a monthly basis."
Now stop and consider this for a moment. Let's say that bands playing there did, in fact, play cover songs. Well then - the audience heard a bunch of music which they might then be interested in buying. Instead, the morons from the music industry would like to ensure that only original music gets played (because that's what bar owners would do, rather than have to pay an extra fee). What' the end result of that? A less diverse range of music heard by the audience, which will result in fewer experimental sales.
The music industry has moved beyond protecting itself, and straight on to suicidal behavior.
This sounds like outsourcing taken to a bad extreme:
The reader was in the market for new Veritas Backup Exec software and was exploring his supplier options. "Dell offers a product called the Dell PowerSuite Veritas Backup Exec Server," the reader wrote. "It appeared to include several of the Backup Exec options we needed at an attractive price. Unfortunately, my quest to find out exactly what it includes proved to be an exercise in futility. I spoke with four different representatives at Dell, three of them sales reps and the other from tech support."
While some of the reps he spoke with had thick accents, the real problem was that none of them seemed to have any information. "What did I learn from these four people?" the reader wrote. "Absolutely nothing. I spent 90 minutes on the phone on hold and got nowhere. The sales reps just read the website to me over and over again. I guess they assumed that I couldn't read it myself. I explained to them exactly what I needed to know in terms a child could understand and they still could not grasp what I was saying. I got so aggravated that I finally hung up. Miraculously I got a call back five minutes later and spoke to another rep, but he turned out to be no more helpful than the others. After fifteen wasted minutes he told me he would research it and call me back."
The thing is, it's very, very dangerous to push a core function (like sales) out. Why? In order to sell, you need to have committed people who want to sell your product, not time-fillers reading from a script. There's a secret underbelly to outsourcing support as well - it makes all your post-sales customer contacts suck, which in turn lowers the liklihood of a future sale. There are at two companies that have hurt their chances of selling me a new product because of that - the outfit that now owns Replay TV and Symantec.
With Symantec, I wanted to renew my anti-virus subscription, so I went to their website. As it happens, I made a mistake on the form and got a renewal key for the wrong product. I was willing to cut them some slack since it was my error, but I ended up talking to people who I could barely understand - and it was also clear that they could barely understand me. Once it became clear that I had the wrong key, they got me a good one. The entire experience would have taken minutes (instead of over an hour) had I been speaking with someone who understood what I was saying
I'm sure that outsourcing tech support saves money in the immediate "balance sheet" way. What I'm also sure of is that it costs future sales to existing customers, as they get frustrated and angry dealing with a communications problem they didn't ask for.
Looks like someone set up a planet Smalltalk site. I don't see a feed for the aggregated site, but there are subscription links to all the blogs that are listed - including a few I had missed.
I was talking about dangerous power in this post, and I got an email comment on another doozy you can get enamored of - #doesNotUnderstand:
The first time you realize that you can implement #doesNotUnderstand: in your own classes (or in any class), it can lead to some truly dangerous (and hard to follow) Smalltalk code. Here's an example - something I used to do a lot of when I first learned Smalltalk:
update: anAspect with: aValue from: aModel [anAspect isKeyword ifTrue: [self perform: anAspect with: aValue] ifFalse: [self perform: anAspect]] on: MessageNotUnderstood do: [:ex | ex return]
The intent here is to handle an inbound event (sent via dependency) - and let events we get (but don't care about) fall on the floor. Why is this dangerous? Well, notice that the "let the events we don't care about fall" mechanism is a MessageNotUnderstood handler. That means that if any MNU is raised downstream from the #perform: (i.e., not in trying to perform the event, but in trying to handle it) - it will get swallowed. This leads to errors that are nearly impossible to diagnose (trust me - I've written myself into this corner). In general, you want to think twice (or more!) before you decide to handle an MNU in "normal" code....
One of the interesting questions that came up when I taught a Smalltalk class last week was on "uniqueness" - the students wanted to know about things that Smalltalk was capable of that would be hard (or impossible) in the languages they knew. Most of the students were Java/C/C++ developers, so it wasn't hard to find a few things that stood out:
- Classes are just objects
This one often throws people. When all you see is constructor code, realizing that a class is just another object can be an epiphany. I was able to get that point across by showing them class instance variables - and pointing out that they are simply instance variables for the class. This isn't a hard idea to get across - but it demonstrates the differences between the Java notion of a class object and the Smalltalk notion of a class object quite well.
Most people come into a class expecting to learn about a fixed set of reserved words that define control structures. When you get to blocks in Smalltalk, it's just a little different. One of the things that really helped here was the debugger - I was explaining how #whileFalse: worked, and I used the debugger to show the power of blocks. Walking through the code in the debugger really explained things - and made it clear that blocks allow you to define your own "control structures" in Smalltalk.
It's not that you can't do the kind of message dispatch that #perform: allows for in Java - it's that in Smalltalk, it's simpler and more convenient. That's a mixed blessing, of course - every Smalltalker I know (including me) went dynamic message creation crazy sometime during their first year or so of Smalltalk - before realizing that over-use can make code impossible to follow. Every language has landmines you can step on - this is one that most developers run into fairly early in Smalltalk.
In any event, these topics engendered a lot of good conversation in the class, and I think they helped demonstrate the power and flexibility of the language to the students. One other thing I found to be a great help - the workspace created by Ivan Tomek that we ship with the NC product. It has a lot of great examples that helped quite a bit. I should probably talk to Dave Buck about this stuff - he's got a lot of experience teaching Smalltalk, and offers training classes now.