Tuesday, November 29, 2005

Agent Remote Control

I've posted a new version of my Agent Remote Control project. You now can not only output Microsoft Scripts, but it now also generates an HTML page that can only be run in IE (because it requires ActiveX). I went looking through the code and I was shocked. I took the source down off the site until it can be properly cleaned up. It was atrocious. So, I've been spending time cleaning up code. I fixed a lot of bugs as well. I'll put the source up later. But, for now, download the application and be prepared to lose a lot of hours laughing. If you want to know what Agent does, look at my quotes page in IE and you'll see a little character appear and talk. Remote Control allows you to script him.

Thursday, November 24, 2005

Dolphin 6 is a Reality!

If you didn't already know, click your way to Object Arts and take a gander a Dolphin6! It's finally here! Christmas came early. I'm so excited! Happy Thanksgiving today. Make sure to eat lots of turkey and play with the Dolphin...=)

Tuesday, November 15, 2005

Stephane Ducasse

Well, I found a slew of articles last night written by Stephane Ducasse. He is my new personal hero. Everytime I get to thinking about a problem, it appears that he has already paved the way for me. For example, my thoughts on metrics via source code changes, he's fully completed them with the article, Finding Refactorings via Change Metrics. I also learned quite bit on metrics from "Metrics, Do They Really Help?" It pointed me in several great directions to book. It's just incredible. His website is overflowing with great computer science research. I keep coming back and finding new gems everytime.

He's an active member of the Squeak community, author of several books (did I mention that they rock too?), and he maintains the Smalltalk book list. I'm so glad to have someone like him in my community. I hope to someday meet him in person and shake his hand. Until then, I'll keep reading. I've got much to learn! I would like to thank Stephane for all of his great work and being such a good mentor through his writings!

Monday, November 14, 2005

Alternative Methods of Testing

This was a topic of discussion at Smalltalk Solutions after Niall Ross' talk on concurrency testing. The floor was opened up for other methods of testing a system. Michael-Lucas Smith brought up how he used SmallLint (a tool that exposes a plethora of code smell symptoms) to prevent certain code smells from entering the system. I went on to explain how I used what I called "Source Code Tests". Basically, I make tests that check compiled code for forbidden method calls in the system.

It's a topic I've been thinking a lot about lately and I'm planning on presenting some of my thoughts at the next Smalltalk User's Group Meeting. Basically, I feel that testing is crucial to a successful project. Unit tests are great for finding errors quickly. Wouldn't it be great if we could use tests to help us find other problems rapidly? Michael-Lucas Smith's usage of Lint in his unit tests stamp out code smells before they even get started. I started to write "Source Code Tests" to stop the usage of APIs that cause performance problems from getting out of hand. It's worked great because it stops bad code from starting or continuing. What other ways could we possibly test? Here's some additional testing methods:
  • Source Code Management provides historical information on code that could be problem sources. Think about it. If we see that one class is changed more frequently than any other class, then that might indicate a potential god class or at the very least a class that needs to be closely examined. Why does it change so often? We could ensure our design guards properly against unstable classes in the system and so that they do not effect the stable portions. You could test for rate of change (if there's a huge jump, then your tests could warn you. Maybe they shouldn't fail, but a warning color of yellow might be indictative that the code is correct, but there is a design problem.

  • Metrics calculations can be useful for uncovering design smells. You could place thesholds in your tests for whatever metric calculations your team wants to track. If a certain threshold is passed, then a test fails. This makes you look at the offending code right away and stops design smells in their infancy.

  • Method wrappers during execution of unit tests and verifying the results. For example, mark your private methods (via pragmas or method categories) and check if any code called it externally. This is just one simple example. I know there's more lurking.

And that's just a few, I'm sure there's more. The point is to look at what problems would you like to know about early and fix? The earlier we find problems, the easier they are to fix. Anything that will help find code and design smells is a good thing. What other tools do we have now (like Lint and Metrics) that we could use from our tests? It's a fun topic to think about! Of course, I welcome any feedback because I want to know how I can not only better the correctness of my code, but my design as well.

Sunday, November 06, 2005

Why XML?

So, I've been playing around with Ajax and rich client web stuff lately. I wonder why not just use Javascript to pass data instead of XML? I know there's frameworks to read/write serialized XML objects out, but why not Javascript? I found that Javascript was easier to traverse the objects and I was able to add behavior (of course, you need to be careful on pushes to the server to insure against malicious code, but I digress). So, I get the power of objects and not just data structures. If you're pulling information, Javascript seems like such a better match. It's a more natural fit for the client side and it's not hard to generate/parse javascript code (if it's just data as in XML). XML traversal is kludgy at best on the client side. Maybe an XPath framework would be nice, but why go through the trouble? You have a perfect representation that fits naturally with no fuss. I wonder if its another case of we-have-to-use-XML-because-it-is-portable.

Declarative Programming

Is declarative programming going to become more important for the richer client web? I've been playing around with Ajax programming. It's easy, but one thing keeps coming up: the coupling of front and back-end. I see it as a possible source of duplication. It's not like it's a new problem either. I've seen several projects where the client and server validation code was duplicated. It's insane to write the same code in two or more languages! Why not just one?

Well, there is already some help already out there. There are a few implementations of Javascript engines out there (for example, Rhino for Java, which I have used on several occassions, is excellent). Why not write your validation code in Javascript? You can then execute the same code on the client as you do on the server. We've just removed duplication, but then you must decide where to draw the line. And if you're not careful about what goes in Javascript and what doesn't you can end up in the same boat as before. But, running Javascript on the server for validation is a possible solution. But, Ajax will bring even more code to the client.

This is where I think DSLs and declarative thinking will shine. Why? Well, I can create a language that is intepreted on the server sid, and is used to generate the client side Javascript code. Tt will be more readable, faster, and closer to the user's language. Ruby and Smalltalk make DSLs a snap. I used a simple use of DSL for generating my Javascript code in my Agent program. I simply used polymorphism and exchange the real Agent object with one that generates the Javascript code. No duplication.

I think much like we have OO-relational mapping frameworks (and we don't have to deal with SQL in only limited contexts), we'll have server-client code mappings that will take care of the Javascript code for us. So, we can stay mainly in one language and not duplicate code. I've worked on a small Ruby framework to serialize Ruby objects as Javascript objects (it was very simple and just a proof of concept), but we also need to transfrom methods to Javascript as well (like the validation rules). A DSL will help in making that job easier. Much like in a OO-relation mapping framework, we make the distinction between storable/non-storable objects.

Ajax is simple to program, but I can see the complexity rising in any project of sizeable length. Much like we don't have to think about SQL with great frameworks like ActiveRecord, TopLink, Hibernate, and Glorp, I think a new breed of frameworks will emerge for Ajax that will make us not have to worry about Javascript as much. it's not that Javascript is bad (I love the prototype dynamic nature of it), but having duplicated code/definitions are the enemy here.

Of course, I wouldn't be suprised if people were not already working on them. I was thinking of playing with some implementations (for example, writing rules with blocks and using the rules for code generation of Javascript and intepretation on the server side). But, we'll see. It'll be a lot of fun to watch! Especially since Ruby On Rails already has Ajax support (but, I don't know how far they go). Rock on!

Wording and Definitions

A common problem when you put two humans into a room is misunderstanding in language. Different backgrounds, perceptions, or outlooks give people different definitions to words. I generally strive to use common words in a project so that we can avoid some of this confusion, but it always seems to creep up. The thing that surprises me is it comes up at the weirdest times. Usually, in heated discussions when in a fever of disagreement, you find you were arguing over definitions. And not the intention of getting the goal accomplished. A relief comes over the room and consensus occurs. But, you feel like the time leading to it was wasted. If only we could have only come to the conclusion sooner!

What's the solution? Project dictionaries are excellent for this. Create a spreadsheet with the words of the domain. Write the definitions from the dictionary and the end user's perspective. And then stick to them. But, this only addresses the business domain words, what about everything else? For example, we recently had a difference of perception over the definition of the word, "collaboration". At first, I was shocked that we could differ on such a common word. But, the ensuing discussion helped me realize how better to deal with certain members of my team. I learned how to be a better team partner to them.

The rush of wasted time came over me again and I quickly brushed it off. I realized discussions of definition are not wasted time! But, opportunities to see how people perceive their world and to more successfully communicate with them. Sure, it's a long way to get to the point, but the journey is what is important here. What I used to think of as wasted time, isn't.

Much like the discussions of the project dictionary are good. Those long detours over definitions are good as well. But, the outcome is different. The project dictionary is an aid for understanding the problem, and differences of definition allow us to learn more from our team partners.

Saturday, November 05, 2005

Omaha.st

It's time for the Smalltalk User's Group. It snuck up on me. So, I thought we could bring in our favorite pieces of Smalltalk code and willing to discuss. It sounds like more fun than we should be allowed to have. Bring your elegance!

Here's all of the details:

When: November 8, 2005, 7pm - 9pm
Where: Offices of Northern Natural Gas
1111 S 103rd Street
Omaha Nebraska 68154

Office is at 103rd & Pacific. Guests can park in the Northern visitors parking area back of building, or across the street at the mall. Enter in front door, we'll greet you at the door at 7:00pm. If you arrive a bit later, just tell the guard at the reception desk you're here for the Smalltalk user meeting in the 1st floor training room.

Omaha.rb

It's time to hold another great meeting of the Omaha Ruby User's Group. We'll be discussing everything about Ruby. I recently wrote some Ajax code and I thought it might be nice to compare the "raw" way and the "Rails" way. So bring your favorite pieces of Ruby code and your curiousity. Hope to see a lot of people there! Make sure you sign up on the mailing list. Here's the information of the when and where:

    When:November 7, 2005
    Where:Panera @ Eagle Run Shopping Center
    13410 West Maple Road
    Omaha, NE 68164

Sunday, October 30, 2005

New Me

Well, I cut my hair off recently and everyone that I know has been curious as to what I look like now. So, for the curious, here is my post-metal locks:




My wife was kind enough to take the pictures and touch them up! I must admit I love it. Rock on!

Saturday, October 29, 2005

Early Binding Gotchas

I recently ran into code like this:

public class MyType {
public boolean equals(Object other) {
if (other == null) return false;
if (other == this) return true;
if (!(other instanceof MyType)) return false;
return equals((MyType)other);
}
public boolean equals(MyType other) {
return someValue == other.someValue;
}
}

Nothing really stands out as being WRONG, does it? It's making clever use of overridden methods and it looks like it might even save us some time if we know the object ahead of time (equals(MyType)). And that is where the "gotcha" is! Let's look at a test shall we?

public void testEquals() {
MyType myType=createExampleMyType();
MyType otherType=createAnotherExampleMyType();
MyType nullMyType=null;
Object nullObject=null;

assertTrue(myType.equals(myType)); //correct
assertFalse(myType.equals(null)); //correct
assertFalse(myType.equals(otherType)); //correct
assertFalse(myType.equals(nullObject)); //correct
assertFalse(myType.equals(nullMyType)); //This thows anException! WHAT THE @#$%^&!!
}

OK, let's break this down shall we? The first test binds to equals(MyType) because the java compiler early binds its arguments in message sends. It figures out the argument types from the variable types used and finds the appropriate message to call at run-time (basically, it early binds the arguments and late binds the receiver). The second test binds to equals(Object) because it finds the most generic method it can. Since, we didn't say what type of null to use, the compiler picked Object for us. Next up, the third test binds just like the first, since we know the types of arguments. The fourth test is now trivial to us, right? Which leads us to the final and most troublesome test. Bascially, equals(MyType) got bound because the compiler doesn't know that we left that good ole null in there! So, where we thought we were safe, we are not. We just bypassed all our null checking code. Oh poo...

So, what can you do?

public class MyType {
public boolean equals(Object other) {
if (other == this) return true;
if (!(other instanceof MyType)) return false;
return equals((MyType)other);
}
public boolean equals(MyType other) {
if (other == null) return false;
return someValue == other.someValue;
}
}

The simple answer is to move your null check into your equals(MyType) method and be done with it. Just remember that null and early binding are gotchas not to be taken lightly when using overridden methods.

Great Idea

I was checking out Fall Of Troy's website and clicked on the tour dates. Uninterestingly enough, it shows a list of tour dates. I saw that they were going to be in Iowa and I thought, "Wow, that would be a cool show!" So, I click on the link and it takes me an info page telling me all the usual stuff (venue, address, time, ticket prices, etc), but with one small difference. You can add yourself to the list of attendees! What a cool idea! It allows you to exchange emails with people before the show and talk music. I wish the internet had been bigger when I was in college. We used to just get to the show early and hang outside to meet new folks. It was a blast. Anyway, I thought it was a great way to meet people wo are interested in the same things and who doesn't need more friends?

CD Extra Tracks

I hate added silence to get to the bonus tracks of a CD. I don't mind a 3 second delay, but when you make it more than that: You're testing my patience! And most of the time, the extra song was not even worth the wait. So please, I plead with record companies to stop adding silence to wait on the impending bonus track that will not rock my world. Thank you.

Friday, October 28, 2005

Cute And Fun

Why do the Lisp dudes have the best cute ideas? First, it was Schememonster and now, a cool alien logo. I love the idea behind it too. It's kind of poking fun at themselves and at the same time, letting the world know that we are DIFFERENT and that's GOOD! It's inviting in a "Jump on in, the water's fine!" kind of way. It's anazing how much the Lisp and Smalltalk inventors just got it right. It's even still amazing people are still discovering things that you can do with both. Rock on!

Wednesday, October 26, 2005

Being Sick Sucks

I've been ill for this week and I'm aggravated with it now. Nebraska has killer viruses that knock me out for a week at a time. I've been sleeping all of the time and I'm only conscience for only a few hours everyday. It's viral and the only thing to do is medicate and sleep it off. I hate being sick. I was excited about this week at work too. Grrr. I can't even read an article without spacing into neverland. Oh well, it's back to bed for me. And there is so much good material to read from OOPSLA 2005. Grrr. I hate illness!!!

Sunday, October 16, 2005

Some Days Are Meant For Play

I read Michael Lucas-Smith's blog this morning and immediately downloaded his Higher Order Methods package in my VW image and read the documentation on it. I thought to myself, "WOW! This would be a nice addition to my Lazy Collections framework!" So, instead of working on Needle in VW, I update the Lazy Collections framework in Squeak. Shame on me! But, it was SO MUCH FUN! The implementation is different from Micheal's, but I used a similiar implementation to the internal's of Lazy Collections. Basically, this is just me playing around. I made a few additions like prepending each to common methods (like #printString is #eachPrintString). It cleaned up my test a lot! Just download it and compare the #test method with #testIterator. The iterator version uses Higher Order Methods. I like the shortened syntax.

It was a fun exercise in blocks and doesNotUnderstand! OK, I'm going back to my regularly scheduled program. I would like to thank Michael Lucas-Smith and Travis Griggs for the inspiration. Your code as always is a lot of fun to read and study.

You can get the new version of LazyCollections on SqueakMap.

Saturday, October 15, 2005

Poor Interface

You know you have a bad interface when there are store fronts to sale stuff on your site. I don't know, but I would be embarrassed if I was the head of Ebay. There's a whole niche maket springing up simply because your user interface is so hard to use. So, people will take their stuff to someone else to deal with it. I know I've seen at least two of these stores around my neighborhood and they've even been spotted in movies (in 40-year Virgin, it was a part of the story!)

Monday, October 10, 2005

Re: Re: Dolphin's Command Framework

I got the following comment from Günther regarding this previous discussion:
Blaine,

I tried to get this to work with Menus and ContextMenus in the ViewComposer, without success.

Could you give us a for dummies description how to do that?

Thanks,

Günther, guenni

OK,
I've been writing a little utility for myself to manage my Mp3s in Dolphin and here's the code that I use to add commands to a context menu (when you right-click on a model object in a tree view):
setContextMenuFor: aModel 
| menu |
menu := aModel isNil
ifTrue: [nil]
ifFalse:
[| contextMenu |
contextMenu := Menu description: 'IRiver'.
aModel actionItemDescriptions do:
[:each | | command description |
command := each key.
description := each value.
contextMenu
addCommand: command
description: description].
contextMenu].
self tree view contextMenu: menu

The interesting bit of this method happens in #addCommand:description:. The command argument can be anything that understands the protocol #queryCommand: and #value. Symbol and MessageSend both do as well as my CommandMessageSend that I discussed earlier (since it is a subclass of MessageSend). Here's some examples of #actionItemDescriptions implementations that are called on the model in the above code:
Mp3Respository>>actionItemDescriptions
| result |
result := super actionItemDescriptions.
result
add: (CommandMessageSend receiver: self selector: #syncBackup) -> 'Sync Backup'.
^result

Mp3Root>>actionItemDescriptions
| result |
result := super actionItemDescriptions.
result
add: (MessageSend receiver: self selector: #save) -> 'Save'.
^result

I tried doing it through the ViewComposer and it can be done, but it's more trouble than it's worth. I decided to generate the code dynamically if I needed it. It's just as easy to add it through the code as it is to add it via the ViewComposer. I hope this explanation helps. I was trying out to see how I liked the model answering the things that it could do without knowing about the GUI. This was a cut at what it would feel like. Feel free to email me! =) I'll try to get on the IRC discussion more often.

Application vs. Data

Ravi Venkataraman wrote:
It is unfortunate that many people in the software industry do not understand that applications come and go, while data remains for much longer.

Is it that really true? I've been in the business for now over 10 years. And I've never seen the lights turned off ANY application. In fact, I've seen many mainframes persist when they should have been replaced. The application and the data is the whole picture. The application has the business logic and knows what to do with the data. I know our experiences will be different and our mileages will vary.
If, as you are suggesting, every application defined its own terms and essentially created its own data model, how can the enterprise ever know anything? Say, for example, every department and system defined "customer" in its own way, then how can you answer the simple question, "How many customers do we have?"

I think we're looking at the same problem through different lenses. I think applications should have access points to get information that's inside of them. I believe in encapsulation. It's the classic black box vs. white box. I see the problems in both and I wonder if we could come up with a mutual solution. A common database makes it easier to find "how many customers do I have?", but what if all applications had common access points and you could answer the same question? They both require expertise in different areas. Is one better over the other? The more I think about it, I come to the same conclusion: Both require planning and thought. You can certainly paint yourself into a corner with both. Maybe we should have a mixture of both. Can we have a mixture of both? What would that look like? I would love to discuss this further...
The fact that data modellers create unchangeable, unmaintainable data models is a reflection on their lack of competence. Most data modellers know zilch about data modelling. Just like the vast majority of Java developers know nothing about OO concepts.

I think if you look at any human endeavor, you will find a bell curve. Few will be awful, few with be great, and most will be average. I think a lot of times data modeling gets into discussions of performance way too early (much like getting into performance issues too early in OO design causes problems). Good data models are hard much like OO models are hard. I think I'm a pretty good data modeller, but I could be wrong. Do you have any good books that I could read? I'm always into bettering my craft.
The right approach is to build the data model from an enterprise point of view, then use database views to show the application specific representation. That insulates the application developers from the actual implementation of the data model; and takes care of all the problems you mention.

I believe this is a slippery slope. Common OO models to reuse across enterprises have been tried and I've seen them get stumped on "simple" questions. What seems straightforward for one part of the enterprise might not be for another. It's the difference in context between organizations. Vague language is the main culprit. Common terms might mean different things to different parts. To get them to agree and use them consistently is another matter. RDMS answers the problems of making sure my tables have integrity, but what about values in fields? For example, what about ranges? Most business rules are complex beasts and they usually go beyond the integrity constraints of RDMS. And to get different parts of a large organization to agree on the business rules for each segment is a hard problem. Like I said before, maybe we can discuss this to come up with a better solution.

The main purpose of a RDBMS is to enforce data integrity. Applications used to enforce integrity, but that failed more than three decades ago. That is why the shift to RDBMS occurred. The network model and the hierachic model, along with using files for storing data, rather than a higher level abstraction, created many problems.

Oh, I'm glad we don't store things in files anymore! I just think applications should have access layers that allow outside applications to intergate their information. Allowing an outside application access a public object model is powerful stuff. It allows the outside application to even update my system because I can enforce my business rules while keeping my data encapsulated properly. Anyway, thanks for the history lesson, but I know the reasons why RDMS came into being.
You seem to be suggesting that we should go back to the 1970s and try things that were known to have failed at that time. Why do you feel it should succeed this tme?

I am in no way suggesting we go back to the 70's. Most mainframe system provided no way for outside system to access their internal data. Most of the mechanisms have been added afterward. I'm suggesting a layer of abstraction above the database. It takes a little more effort to add a component layer to an application, but it's absolutely needed in enterprise settings. But, let's discuss and not give history lessons or bad assumptions:
The original weblog article is flawed in so many respects that one is filled with despair.

If the suggestion is that each application develop its own data model, then what happens to data integrity? How are the common integrity and business rules expected to be applied across all applications? Duplication? What if one application modifies the code in a manner inconsistent with the business rules?

I suggest that you learn a little bit about RDBMS before talking about them.

I suggest you don't assume what my background is. But, let's talk like educated and intelligent beings. I believe applciations should manage their internal data integrity and provide a model to the outside world. I believe in encapsulation at the application component level as well as the object level. I'm opening up the discussion. You make a lot of valid comments and I think we can come up with a cool solutioon if we concentrate on our goal and not tearing each other down.

Sunday, October 09, 2005

Omaha Smalltalk User's Group Meeting

This month I will be presenting Seaside, Avi Bryant and company's brilliant continuation-based web framework. People have been requesting it again so I thought it was time to do it again. It should be a lot of fun as always!

Here's all of the details:

When: October 11, 2005, 7pm - 9pm
Where: Offices of Northern Natural Gas
1111 S 103rd Street
Omaha Nebraska 68154

Office is at 103rd & Pacific. Guests can park in the Northern visitors parking area back of building, or across the street at the mall. Enter in front door, we'll greet you at the door at 7:00pm. If you arrive a bit later, just tell the guard at the reception desk you're here for the Smalltalk user meeting in the 1st floor training room.

Saturday, October 08, 2005

Tacky

This should be filed under Tacky. I can't believe they would actually sell this t-shirt. I was shocked and saddenned. And we wonder why more women do not get into our industry?! We are not inviting with crap like this.

Get Up

Need apparel on the positive side? What a cool and nefty idea. T-shirts with positive messages. How fun. Now, I wish someone would put all of the funk phrases on t-shirts (from P-funk, Graham Central Station, and EW&F). Nothing really more to say, I just really liked this idea.

Sunday, October 02, 2005

Shared vs. Mobile Data

Alex Bunardzic writes about "Shared Data and Mobile Data" in response to his article on "Should Database Manage The Meaning?" He makes an important distinction in the debate. There's people who think the database should be the central point and then, there's those of us who think data should be mobile (not centralized). I think the folks that believe in centralized databases should read William Kent's "Data And Reality" book to see the problems with that view. It basically boils down to meaning. Different projects will view what might seem to be the same data differently. We might even use the same terms, but have slightly different meanings. It's the slight difference that kills the shared database model. Not to mention, that over time shared database models become unchangeable and unmaintainable because of the massive amounts of coordination it takes to make a change (even with volumous documentation which is usually out of date anyway). Who wants to make a change and be held accountable for every system they break? It becomes a "let's just hack this field that only we use so we don't have to go pull teeth". Ouch. It's easier to just change your code than burden evryone else (who may not want to make ANY changes to their code at all...it's not in their budget) I've seen this scenario more times than I care to count.

Mr. Kent's book exposes these problems and lays them out. The book is great for exposing the problems that basically boil down to humans having ambigous language. Even though our computer languages are strict, our meaning still is king and that's the disconnect. It's the same reason that common business objects that cross enterprise divisions are problematic as well. They each have their own meaning of various words used to label things. It's best to have each system to have their own database and have distinct boundaries where they exchange information. Everyone keeps their definitions (which makes sense to their users) and makes conversions on the boundaries.

Eric Evans' excellent "Domain-Driven Design" offers the solutions to the problem. In fact, he has an example in the beginning of Chapter 14 (Maintaining Model Integrity) that explains it. Different systems might be working on what seems to be the same model, but they are looking at it from different contexts. Each system should have its own "bounded context" of the model. Here's an excerpt from "Domain-Driven Design" that explains it clearly:
Explicity define the context within which a model applies. Explicity set boundaries in terms of team organization, usage within specific parts of the application, and physical manifestations such as code bases and database schemas. Keep the model strictly consistent within these bounds, but don't be distracted or confused by issues outside.

He continues to make a point of keeping the boundaries distinct (don't allow them to blur) and be explicit in communication with outside systems (by using "context maps" for conversion to/from outside systems).

The bottom line is keep your systems distinct and avoid the allure of sharing common domain/data models. Keep the boundaries distinct and exchange information with outside systems. I wouldn't even allow common exchange formats across systems (It runs into the same exact meaning problems). Define the exchange for each system (A different DTD for each one if you use XML, I'm not saying to not use standards, just don't define a common DTD for all system exchanges across the enterprise). Don't be lazy. Let your system keep the meaning and don't let it get watered down. Sharing allows meaning to be blurred (and misused) and this lets the bugs in. Data warehouses sound like good ideas, but really your duplicating the meaning to pull everything together. An agent system would be a better answer where it gathers the information from each of the systems at their boundaries. Since the agent would be its own system. It's a harder path to follow, but it's the one that allows your systems to continue to grow and not stagnate. The minute you buckle a system together with another, the stagnation will begin and the cost curve will start to rise.

Firefly: Huh?

I was excited to see Serenity until I saw my first episode of Firefly. I can see why the Fox executives killed it. I know I would have. Which brings up the question: What am I missing? The show I saw was little more than take offs of previous Star Trek (original series) episodes, bad scripting, bad acting, and over-worked sci-fi cliches. It basically killed my desire to see the movie. I saw the previews again and the poor scripting came up in it as well ("Do you want to captain this ship?" "YEAH!" "Well, you can't!"...That's GOOD?). I don't know I'm just tired of Star Trek sci-fi. It's been done to death. Give me Planet of The Apes, new Battlestar Galactic, Logan's Run, Philip K. Dick, and 2001 any day. Give me sci-fi that makes me think (as you can tell, I like sci-fi with political themes). Am I truly missing something? Am I not supposed to take it so seriously? Is it meant to be so bad that it's good? I'm at a loss here.

Thursday, September 29, 2005

Omaha Ruby User's Group

It's time to hold another great meeting of the Omaha Ruby User's Group. We'll be discussing Rails, Ruby, dynamic languages, and anything else we can think of. So bring your favorite pieces of Ruby code and your curiousity. Hope to see a lot of people there! Make sure you sign up on the mailing list. Here's the information of the when and where:

    When:October 3, 2005
    Where:Panera @ Eagle Run Shopping Center
    13410 West Maple Road
    Omaha, NE 68164

Wednesday, September 28, 2005

What He Said

I couldn't have said it better myself.
From Vincent Foley:
I compared dynamic languages and Java with riding a bike; in dynamic languages, you ride on two wheels and you get where you want pretty quickly. You can fall if the road is slippery, if you hit a rock or something, but with a little experience, these cases rarely occur. On the other hand, riding a Java bike is like having 8 wheels to make sure you don’t fall over, 10 people constantly around you, ready to catch you should you fall. You may be safer, but you’re not getting places faster than the dynamic biker.


Right on! Can I get an amen?

Monday, September 26, 2005

How not to make money

On the first visit to your site, I get this:
Mod_python error: "PythonHandler mod_python.servlet"

Traceback (most recent call last):

File "/usr/local/lib/python2.4/site-packages/mod_python/apache.py", line 299, in HandlerDispatch
result = object(req)

File "/usr/local/lib/python2.4/site-packages/mod_python/servlet.py", line 1464, in handler
servlet.prep()

File "/home/hosting/users/metald/web/index.mps", line 23, in prep
SitePage.prep(self)

File "/home/hosting/users/metald/lib/pages.py", line 42, in prep
HTMLPage.prep(self)

File "/usr/local/lib/python2.4/site-packages/mod_python/servlet.py", line 593, in prep
timeout=self.session_timeout)

File "/usr/local/lib/python2.4/site-packages/mod_python/Session.py", line 389, in Session
timeout=timeout, lock=lock)

File "/usr/local/lib/python2.4/site-packages/mod_python/Session.py", line 294, in __init__
timeout=timeout, lock=lock)

File "/usr/local/lib/python2.4/site-packages/mod_python/Session.py", line 132, in __init__
Cookie.add_cookie(self._req, self.make_cookie())

File "/usr/local/lib/python2.4/site-packages/mod_python/Session.py", line 160, in make_cookie
c.path = dirpath[len(docroot):]

TypeError: unsubscriptable object

Ouch...Talk about bad first impressions. This is what happened when I tried to go to Metal Direct. I guess they don't like customers.

Sunday, September 25, 2005

Private: The Enemy of Extensibility

I was shocked to find out tonight that junit.runner.ClassPathTestCollector didn't account for tests in jars. OK, easy enough. I look through the class and find a methood called gatherFiles(File,String,result). It takes a file and determines if it is a test class. Well, a simple check to see if the file is a jar, add the class names of the entries which are tests to the result, and we were in business, right? Well, that's what I thought! So, I overrode gatherFiles, added super to let it do its job, and then, added my jar functionality. Simple right?! It didn't compile. It seems gatherFiles is a private method and I didn't have any visibility for the super. OK, I then just copied the original gatherFiles in place of the super and a little gentle refactoring. Everything compiled, but it worked like the old one. It then struck me. You can't override private methods. GRRRRRR! So, I wound up copying the remaining methods that I needed and removed ClassPathTestCollector as my superclass. It shocked me to know what should have been a simple refactoring, turned into a lot more, and it forced me to commit the worst of all sins: Duplicate code. Oh, did you want to see the jar code? Here you go:

protected void gatherFilesInJar(File jarFile, Hashtable result) {
try {
JarFile jar = new JarFile(jarFile);
try {
Enumeration enumeration = jar.entries();
while (enumeration.hasMoreElements()) {
JarEntry next = (JarEntry) enumeration.nextElement();
if (next.getName().endsWith(".class") && next.getName().indexOf('$') == -1) {
addToResultsIfTest(next.getName(), result);
}
}
} finally {
jar.close();
}
} catch (IOException ex) {
//DO NOTHING
}
}

Nothing to it! Anyway, it was a fun bit of functionality to add, so that I can find and add all of my tests in my project now. I ran into these issues with private in Swing as well. I just think as designers we should not close our classes. The reason is because you never know what someone might need to do with your code eventually. Sealing means you know best. Just like I wanted to be able to handle jars in ClassPathTestCollector. If the original designer had thought of that, then he/she would have added that capability. Instead, they sealed off the class and forced me to sin. Don't make the same mistake.

Tuesday, September 20, 2005

Private Testing

David Buck and Charles Monteiro have been discussing how to make sure "private" methods in Smalltalk stay "private". Both have great techniques and it of course got me to thinking: "What a great use for unit tests!"

In all Smalltalks, we categorize methods of a class. Why not mark the private methods in some way? For example, use "private" somewhere in the category name (private, private-processing, private-accessing, etc). This way we know what should be private and what shouldn't be. It doesn't matter the convention just pick one. Now, that we know the private methods, create an object proxy that forwards all calls to the real object. This proxy would check if the method coming in is "private" and signal an exception if a method is "private" since only outside objects will call the proxy directly (Everything else will behind the proxy wall). Now, just pass the proxy around in the unit test as if it were the real object. Let the unit tests verify that we are not calling "private" methods and we have no run-time costs. Of course, we could get fancy and use method wrappers and #become:, but I will leave that as an exercise to the reader (or maybe a future blog entry?).

The main point of this post was to give yet another idea of how to make sure private methods stay private. I would love to hear more techniques. This technique that I just described is what I call meta-unit-tests. We are verifying meta-information about our program. I've used meta-unit-tests for making sure deprecated API calls are not sent in my code and that certain methods are implemented (ie don't have super that calls #shouldBeImplemented). We have a lot of information available to us at unit test time. We can take advantage of it!

Re: Dolphin's Command Framework

I got a comment from Anand that suggested that I change this code:
CommandMessageSend>>queryCommand: query 
| canSelector |
canSelector := ('can' , query command selector capitalized) asSymbol.
^(self receiver respondsTo: canSelector)
ifTrue:
[query
isEnabled: (self receiver perform: canSelector);
receiver: self receiver.
true]
ifFalse: [super queryCommand: query]

to:
CommandMessageSend>>queryCommand: query
| canSelector isEnabled |
canSelector := ('can' , query command selector capitalized) asSymbol.
[isEnabled := self receiver perform: canSelector]
on: MessageNotUnderstood
do: [:ex | ^super queryCommand: query].
query
isEnabled: isEnabled;
receiver: self receiver.
^true

We got rid of the ifTrue:ifFalse: and the code is clearer. But, something bothered me about it. The MessageNotUnderstood could catch any MessageNotUnderstood further down in the stack (it might not be my canCommandSelector). What is a Smalltalker to do? How about this:
Object>>perform: aSelector onNotUnderstoodDo: aBlock
^[self perform: aSelector]
on: MessageNotUnderstood
do: [:ex | (ex receiver == self and: [ex selector == aSelector])
ifTrue: [aBlock value]
ifFalse: [ex pass]]

This message allows us to do the perform, but check to make sure it's the one we care about. Now, our CommandMessageSend code looks like this:
CommandMessageSend>>queryCommand: query
| canSelector isEnabled |
canSelector := ('can' , query command selector capitalized) asSymbol.
isEnabled := self receiver perform: canSelector onNotUnderstoodDo: [^super queryCommand: query].
query
isEnabled: isEnabled;
receiver: self receiver.
^true

The code is about the same, but now we are only catching the MessageNotUnderstood exception that we care about and not any others. The code is still clean and we see another example of the power of Smalltalk exceptions. And I would like to thank Anand for the suggestion!

Monday, September 19, 2005

Oh Lucky Day

I pre-ordered Coheed and Cambria's "Good Apollo, I'm Burning Star IV" and it arrived a day early this morning. I immediately popped it into the player and was just floored. Great rock music from start to finish. I hear bits of The Cars, Led Zeppelin, Iron Maiden, and a whole bunch more. This is the way power pop is supposed to be. Oh yeah, they get the prog punk tag, but this is just wonderfully written music period. I haven't been this excited by a new band in a long time. I love the way they write incredibly catchy music that you never grow tired of hearing.

And then the mail man arrived with two more packages. I received Clutch's "Robot Hive/Exodus" and 3's "Wake Pig". Oh My God! I've never been blessed with this much good music in one day ever! Clutch is a mix of funk and stoner rock that pleases and 3 is like a blender of styles that just simply works. I guess progressive pop punk would be a tag, but you just have to listen to it.

All 3 albums are incredible slab of originality. Did I mention that they were great. Man, my ears are worn out! If anyone thinks that good rock music died in the 90's or you've been having a hard time looking for original great music. Look no further than these bands!

Great Advice

I have to apologize, but I have to pimp "Streamlined Object Modeling" yet again.
Personify Objects
Object model a domain by imagining its entities as active, knowing objects, capable of performing complex actions.
Talk Like an Object
To scope an object's responsibilities, imagine yourself as the object, and adopt the first-person voice when discussing it.
Do It Myself
Objects that are acted upon by others in the real world do the work themselves in the object world.

Live it, be it, model it! Let the design flow!

Smalltalk Unreadable? Huh?

Spotted this quote in JavaLobby via James Robertson:
Have you ever tried to go back an make significant changes to a large Smalltalk application that you haven't touched the code for in 3-5 years or maybe didn't even a part in writing? Try that some time if you haven't and then tell us what you think of Smalltalk. If a language can't pass that battle test, it sucks. IMO, Java passes that test very well, much better than Smalltalk or C/C++.

OK, I've been there and done that with both Java (revisited old code from 3 years ago) and Smalltalk (revisited old code from 5 years) code bases. Now, both of the code bases were written by me and I didn't have a problem getting back into the code with either one. If you have well-defined names and intention revealing code, then it's NEVER a problem.

But, to get up to speed on existing code that I didn't write is another issue. I find Smalltalk to be easier than any language I've ever dealt with. It generally takes me no time to get up to speed with unknown Smalltalk code. Hell, I've been having a blast going through all of the Dolphin code recently. But, I've had my fair share of problems understanding Java code written by other programmers. And most of the reasons have nothing to do with language. It's mostly a matter of writing intention revealing code. Something that most good coders do unconsciously. I've seen my share of bad code in Perl, C, C++, Java, etc. But, I will say this, I find bad code in Smalltalk is much easier to read and understand. Since there's less rules, there's less to get messed up.

Anyway, it's amazing me that we are still having these discussions. Pick the language you love and write code. Stop whining about everyone else's. Each language has its strengths and weaknesses. I choose Smalltalk because it makes me more productive. If Java or Perl makes you more productive, then go write code in it! I do try to sell Smalltalk, but I don't believe in doing it at the expense of putting down another. I think Ruby, Smalltalk, Lisp, etc attacts a different kind of programmer than Java. And that's cool. There's nothing wrong with it. Now, let the Smalltalk flow!

Sunday, September 18, 2005

Dolphin's Command Framework

When I first started to play with Dolphin's MVP framework for building GUIs, I thought it was interesting. It forced you to keep all of the controller code in the presenter. The view was only responsible for view things, the presenter was the glue, and the model was where all of the magic occured. But, there was one thing that bothered me and that's how you used the command framework. From the examples, you override the #queryCommand: method in your Shell. Well, you ended up with code like this which I absolutely hate (BTW, this is taken from my first MVP application):
queryCommand: aCommandQuery

| command |
command:=aCommandQuery command.
(#(File Agents Help about) includes: command)
ifTrue: [^aCommandQuery beEnabled].
command == #saveAgentTape
ifTrue: [^aCommandQuery isEnabled: self tape name isEmpty not].
command == #recordPressed
ifTrue: [^aCommandQuery isEnabled: self tape canRecord].
command == #stopPressed
ifTrue: [^aCommandQuery isEnabled: self tape canStop].
command == #playPressed
ifTrue: [^aCommandQuery isEnabled: self tape canPlay].
command == #pausePressed
ifTrue: [^aCommandQuery isEnabled: self tape canPause].
command == #generateJavaScript
ifTrue: [^aCommandQuery isEnabled: self tape canConvertToScript].
^super queryCommand: aCommandQuery.

YUCK! If you go searching through the code, you find CommandPolicy, Command, CommandQuery, etc and I thought to myself, "Why did they create so many objects if the code turns out like the above?" The answer is the framework is smart and has a lot of parts to it. So, I browsed the implementers of #queryCommand: and I found an interesting class that implemented it: AbstractMessageSend! Well, the interesting thing is that normally you add commands as symbols to the CommandDescription for things like Buttons and MenuItems. But, you don't have to. You can put any object that understands #forwardTo:! And if you add #queryCommand: to your object to use as your command, then you can allow the command to decide when to enable/disable itself! So, I whipped up a little CommandMessageSend that disables/enables itself by calling a canCommandName method if it exists to know when to disable/enable the command in the menu.

MessageSend subclass: #CommandMessageSend
instanceVariableNames: ''
classVariableNames: ''
poolDictionaries: ''
classInstanceVariableNames: ''

CommandMessageSend>>queryCommand: query
| canSelector |
canSelector := ('can' , query command selector capitalized) asSymbol.
^(self receiver respondsTo: canSelector)
ifTrue:
[query
isEnabled: (self receiver perform: canSelector);
receiver: self receiver.
true]
ifFalse: [super queryCommand: query]
CommandMessageSend>>command

^self

Now, instead of adding a symbol, I add this object. I now no longer override the #queryCommand: method in my Shell class! And the code from above no longer exists! No more case like if statements! It turns out that the Dolphin guys came up with really nice Command framework that works its way from the Command object itself and works it's way asking at each level of Presenters until it reaches the Shell. I can understand doing the simplest possible thing from the examples, but it doesn't show the power that they have given you. There's also a undo/redo framework for your code to take advantage of. Just browse references to the Command class. Fire up those browsers and start looking at that code! Dolphin has a lot of cool frameworks inside (look at DeferredValue for more fun).

Wednesday, September 14, 2005

I Got The Power

I've been spending an hour here and there on a mp3 file management system for myself in between on working on some of my other projects. It's basically so I can move files from my local file system, iRiver, and iShuffle. I've been writing it in Dolphin and having a great time. It's meant to be simple and I add features as I find things annoying. So, a production system it is not. Well, I decided to add drag/drop capability so I could do all my file operations within it. I've done drag/drop in several languages and environments in the past and I must admit Dolphin was the easiest. I looked at a few examples from the development environment and I had it all working within a couple of hours. WOW. I didn't even read any of the documentation. Most of my time was actually spent in the domain getting everything working just right. Most drag/drop frameworks I've used in the past are just a pain in the butt. I was simply amazed. Yet, another example of how nice Dolphin really is.

Ruby On Rails

Word on the street is that Sam Tesla gave a tasty sermon on Ruby On Rails at the Omaha Smalltalk User's Group last night. I couldn't make it because of work committments so I guess he's going to have to do it over at the next Ruby User's Group....=) He made a pdf available, so there's no reason not to enjoy its brilliance. Why do I always miss the good stuff?

Monday, September 12, 2005

Squeak Foundation

Towards an acting and communicating core for Squeak. I think this is a wonderful new development in the Squeak community. It's been a long time coming. I love the following quote too:
We will follow the chicken and pig Scrum metaphor: Doers or Core will have the power to do something and talkers will be less considered, even if we will listen to them.

It seems process is getting in place to fund and direct energy in the Squeak community. I think this is exciting! I would like to thank everyone involved in this. Let the Squeak flow!

Saturday, September 10, 2005

Omaha Smalltalk User's Meeting

This month we will be doing a two fisted meeting! First up, we will show the brilliant Avi Bryant Seaside demo from the Vancouver Lisp Meeting. Then, Sam Tesla has been kind enough to show us Ruby and Ruby On Rails. So, it's going to be a meeting not to be missed!

Here's all of the details:

When: September 13, 2005, 7pm - 9pm
Where: Offices of Northern Natural Gas
1111 S 103rd Street
Omaha Nebraska 68154

Office is at 103rd & Pacific. Guests can park in the Northern visitors parking area back of building, or across the street at the mall. Enter in front door, we'll greet you at the door at 7:00pm. If you arrive a bit later, just tell the guard at the reception desk you're here for the Smalltalk user meeting in the 1st floor training room.

SortedCollection, Block, and Polymorphism

I was having a discussion with a friend of mine tonight and they were having problems with serializing an object. After a few questions, I learned that they had a SortedCollection with a custom block. He was using Dolphin and I mentioned that there were other avenues to take. One such avenue is that he could use another object in place of the block as long at it understood #value:value: and returned a boolean. This is a common oversight because it's hard breaking "type thinking" and to step into "protocol thinking". The type of an object doesn't matter, it's the protocol it understands. Rubyists call this "duck typing". Call it what you want, it's powerful. As a side note, this is why interfaces make programming in Java nicer. So, I showed a quick example, say we take the following code:
| collection |
collection := Array
with: 'second' -> 'turbine'
with: 'third' -> 'earth'
with: 'fourth' -> 'good apollo'.
collection asSortedCollection: [:a :b | a key <= b key]

And it returns:

a SortedCollection(
'fourth' -> 'good apollo'
'second' -> 'turbine'
'third' -> 'earth')

In Dolphin, I can use Message instead of block since it understands the same protcol:
collection asSortedCollection: (Message selector: #key)

Or even write a method to do the comparison:
compare: anObjectA to: anObjectB
anObjectA key <= anObjectB key

collection asSortedCollection: (MessageSend receiver: someObject selector: #compare:to:)

Or we could implement #value:value: on an object and pass that in as the block into SortedCollection. Just remember, to use the polymorphism, luke. We can use these tricks anywhere we use a block (Depending on the number of arguments needed, you might been #value:, #value:value:value:, or #valueWithArguments:). And all of the above sample solutions are serializable...=)

It's great to work in a language that allows you the freedom to be creative and extend it in ways the creators never thought of (or perhaps they did). Let the Smalltalk FLOW!

Domain Specific Languages

I still see old world flat file specifications like the following:







TypeNameDescription
9(8)Some DateDDMMYYYY
9(6)Some TimeHHMMSS
x(20)Lovely NameA Good Name
x(36)fillerIgnore

I thought I would do something different implement the parser as if I was a Lisper. So, here's what I came up with:

recordLayout
^#(
(9(8) someDate asDDMMYYYY)
(9(6) someTime asHHMMSS)
(x(20) lovelyName)
(x36) filler)
)

And what does the code look like to parse it? It's even simpler than I thought:

parse: aStream
self recordLayout do: [:eachLayout | | typeInfo typeLength fieldName converterSelector rawData data |
typeInfo := eachLayout first.
typeLength := eachLayout second first.
fieldName := eachLayout third.
converterSelector := eachLayout at: 4 ifAbsent: [#yourself].
rawData := aStream next: typeLength.
(typeInfo == 9) ifTrue: [self verifyIsNumeric: rawData].
data := rawData perform: converterSelector.
self perform: (self setterFor: fieldName) with: data]

WOW! I now have a method that shows the record layout that could be parsed for creating test records as well. I could even show it to a non-Smalltalker and they would know what's going on. I love the flexibility of Smalltalk! I love adding new tricks to my bag.

XML Generation In Smalltalk

Tim Jones showed a simple way to generate XML in Smalltalk. And then Michael Lucas-Smith showed an even simpler way which is very close to what Seaside does for HTML generation (using #doesNotUnderstand:). In fact, I wrote one for Squeak a long time ago for myself that does exactly what Michael and Tim did (my DNU code calls the Tim-like code and compiles it on the fly so to make debugging easy and future hits quick). Anyway, I found that I needed something different for attributes so I created the ability to churn out XML from arrays. Here's some code from one on my tests:
xml := BtbXmlRenderer on: writeStream.
xml render: #(first arg1: 'value1' arg2: 'value2'
(second (third '"fun"'))
(fourth)
(fifth #sixth: 56)).

And this generates the following XML:
<?xml version="1.0"?>
<first arg1="value1" arg2="value2">
<second>
<third>&quot;fun&quot;</third>
</second>
<fourth/>
<fifth sixth="56"/>
</first>

I made all objects implement #renderXMLOn: so that I can use Arrays, Blocks, or anything else to make it easier to output XML in the future. It also means I can use all three approaches to generate one XML document. I think this is a perfect example of polymorphism and the power of dynamic languages at its finest. So, we have three ways of generating XML and I found that each has its advantages at different times. My point to this post was to show yet another way to generate XML using Smalltalk. Keep the Smalltalk flowing!

Monday, September 05, 2005

FTPlets

Apparently, Avi Bryant made an interesting challenge to create a dynamic FTP server. I love the idea of using existing protocols in creative ways. What about a dynamic CSS or Subversion server? Or even automatically save code to a version control system based on submissions to the FTP server and tags things on a per session basis. I'm excited to hear more as this develops. Can you imagine using existing tools for your front-end? Then, people can use the tools that they are most comfortable with.

Good OO Thoughts

From Steve Dekorte's blog:
The amount to which the program is object oriented has an inverse relation to:

1. the number of arguments passed in message calls
2. The number of instance variables in the objects

I tend to use "7 +/- 2" rule. If I have 5 or less instance variables in my object, then everything is cool. I'm even OK with 7, but 9 is on the cusp of too many. The reason why is because too many instance variables is not only a code smell, but your object is getting away from having one responsbility and needs to be broken up.

Arguments are little bit more restrictive. I try to keep them below 5. Otherwise, you're writing big methods and well, your methods should do one thing and nothing more.

Of course, the rule above is excellent, as is the "DRY, Shy, and Tell The Other Guy" rule from the Pragmatic Programmers. They are just some things that I strive for when programming.

Sunday, September 04, 2005

Rule #67 in Design

NEVER clean up resources you did not create

I hate to pick on Java, but I found a great example of this in the Java API of all places in the javax.swing.text.html.parser.Parser class. I removed a lot of the code from the method to concentrate on the violation:

/**
* Parse an HTML stream, given a DTD.
*/
public synchronized void parse(Reader in) throws IOException {
/* LOTS OF CODE REMOVED */
try {
/* WHACKED */
parseContent();
/* WHACKED */
} finally {
in.close();
}
/* MORE CODE DELETED */
}

Basically, you pass in a Reader object that obviously you have to CREATE. And what do they for you? They free your resource that you passed in. Heaven forbid, you would like to do something else with it. Besides, why would you do that? Well, that's not the point. In design, I NEVER clean up a resource I did not allocate. If it is passed into me, I do what I need to do with it and that's all. On the other hand, if I allocate it, I take pains to make sure I deallocate it. This is what I did in my C/C++ days and it was a great rule of thumb that prevented a lot of problems.

Friday, September 02, 2005

Is That All?

Taken from the comp.lang.smalltalk.dolphin:

> Besides the IdeaSpace, what else is new?

Well, off the top of my head, and in no particular order:
1) New look tools with sliding panes (imaginatively called Slidey Inny
Outey Things, SIOTs) :-)
2) New look Resource Browser with iconic categories and preview pane.
http://www.object-arts.com/dow nloads/6.0/images/d6rb.png
3) New look View Composer with sliding resource toolbox and Inspector
panes.  The View Composer now supports undo.
http://www.object-arts.com/dow nloads/6.0/images/d6vc.png
4) Improved garbage collector giving approximately 20% speed
improvement overall.
5) Compiler now supports true block closures and not just a
Smalltalk-80 block semantics.
6) All code editing is now done using the Scintilla code editor.  This
means we get away from the vagaries of the Windows Rich Text Control
and also we now have auto completion (IntelliSense).
http://www.object-arts.com/dow nloads/6.0/images/d6ac.png
7) New "literal filer" for storing views which opens up the resources
such that their contents can be refactored etc.  Storing resources in
this way also greatly simplifies the image stripping process at
deployment.
8) New Sockets2 package that uses overlapped/blocking calls rather than
asynchronous messages.  The old package is provided for backwards
compatibility.
9) The Refactoring Browser rewrite tool has been included as a plug-in
in the class and system browsers.
http://www.object-arts.com/dow nloads/6.0/images/d6rwt.png
10) The class and system browsers now have a Code Mentor plug-in that
comments on the style of your code.  It runs the analysis in the
background as you work and is based on the SmallLint facility that
comes with the refactoring engine.
http://www.object-arts.com/dow nloads/6.0/images/d6cm.png
11) Views now support background colour inheritance.
12) New TabViewXP view that supports XP-style tab views in all
orientations (unlike the standard Windows control).
13) Dynamic syntax highlighting in all workspaces as you type.
14) Workspaces highlight compilation errors and warnings with squiggly
underlinesand will display help for these when the mouse hovers over
them.
15) Various new view controls such as: SysLink, LinkButton,
MonthCalendarView, SpinButton.
16) Windows XP application manifest is now included as part of the
version resource in deployed executables.
17) Application deployment now creates a complete XML based contents
list of the entire application.  This can be browsed from within
Dolphin using a class browser to see exactly what methods and classes
are present in the application.
http://www.object-arts.com/dow nloads/6.0/images/d6cm.png
18) New Method Explorer which replaces the old Method Browser to
provide a hierarchical trail of browse requests.  The aim, like with
the IdeaSpace, is to reduce the number of open windows while working
with Dolphin.
http://www.object-arts.com/dow nloads/6.0/images/d6mex.png
There are dozens of other minor enhancements and bug fixes and probably
some other fairly major ones that I've forgotten but the above should
give you a flavour of what is coming in Dolphin 6.
Best regards,
--
Andy Bower
Dolphin Support
www.object-arts.com

WOW! That sure is a lot of stuff to pack in for a release. I'm beyond excited. I'm so lusting for Dolphin 6.0. I feel like a kitten that can see the cream, but can't lap it up. Dolphin on!

Thursday, September 01, 2005

What kind of technology do you want to create?

From Donald Norman's "Things That Make Us Smart":
When I speak of the power and virtues of technology, I am referring to soft technology: technology that is flexible, that is under our control. Hard technology remains unheedful of the real needs and desires of the users. It is a technology that, rather than conforming to our needs, forces us to conform to its needs. Hard technology make us subservient; soft technology puts us in charge. Automating tends to be a hard use of technology. Informating tends to be soft.

So, when you are creating your next program or framework, think to yourself, "How would I want to be treated?" I bet you would prefer soft technology over hard. Let's make the user experience better all around. I promise to take the above quote to heart in my future endeavors. Take the oath and let's start delighting our users together.

Tuesday, August 30, 2005

Coheed & Cambria

So, I was watching Fuse with my wife the other night and thank goodness for Tivo. I was enthralled by this one commercial with this great music and montage of creepy images. At the end of it all, it showed the roman numerals, "IV" and that's it. We reversed back and got the band name, "Coheed & Cambria". Well, I googled and got to their band page. From there, I listened to some more samples and I was hooked enough to buy one of their CDs. It has to be one of the most incredible pieces of music that I have heard in a long time. It's pure and simple rock with lots of melodies and harmonies. Gorgous does not do it justice. I can't stop listening to it. I've now got all of their CDs on order and I can not wait until their new album, "IV" comes out at the end of September. If you want an idea of what to expect, it's progressive rock without being pretentious and the albums are concepts based around a science fiction story which they have graphic novels for. I'm getting the novels next week. Mark my words, these guys are going to be HUGE. I hope to make a trip to Lawrence, KS in October to see them. I didn't know people still made ROCK records like this anymore. Apparently, they do and there's a whole genre of bands doing stuff like this. Thoughtful, arty music, but with their feet firmly planted in creating memorable hooks. This is what made Black Sabbath, Led Zeppelin, Yes, and Queen great. ROCK ON!

Sunday, August 28, 2005

Too Funny

I see the next shirt that I'm going to have to buy. CLASSIC! The Ruby guys are really giving java a lot of hell. A light-hearted jab in good fun. Ruby on!

Saturday, August 27, 2005

Excited about Squeak 3.9

Traits will come with Squeak 3.9. How awesome is that? Prepare to have another weapon added to your arsenal. Of course, if you can't wait like me, you can download it now in 3.8 via SqueakMap. Squeak on!

VOIVOD Guitarist DENIS 'PIGGY' D'AMOUR Dead Of Colon Cancer

It was reported yesterday that Piggy of Voivod died of cancer at the age of 45. Wow. It took me years to get into Voivod, but once I "got it", they've been one of my faves. Piggy was an incredible and unique guitarist. He will be missed. I got to meet him at Ozzfest a couple of years ago and they were incredibly nice and appreciative. I can't believe another hero is gone. I will be spinning "Dimension Hatross" and "Nothingface" in remembrance. RIP, brother.

Friday, August 26, 2005

The Future and The Ordinary

Suppose you are absolutely certain that a technology that you know about will succeed. How long will it take to have a major impact? Warning: Technologies take a surprisingly long time to become accepted.

The above quote is taken from Donald Norman's "Defending Human Attributes in the Age of the Machine". He gives insight in why new technology takes so long to adopt and even gives some examples of outmoded technology that we still use (the "qwerty" keyboard). Then, he explains several examples of modern technology and how long it took them to be accepted. The numbers are staggering. The television took seventy years from inception to acceptance! He gives a lot more examples and it's quite the read.

Where am I going with this? I think this applies to computer languages and frameworks. The rest of the industry keeps edging toward Smalltalk and Lisp. The road to Smalltalk was started with C++ (by mimicing OO features) gaining acceptance. Later, it was java (VM, garbage collection) and now, python and ruby (late-binding, dynamic typing, closures, etc). Each jump has taken about ten plus years each. What will the next jump be? I'm hoping it will be toward the image because it's the only piece missing. But, we still have about ten years before critical mass. Are you patient? I think I can be.

Each technology jump toward Smalltalk should be celebrated. I tend to be disappointed with each jump because it's not far enough, but I should be happy. Everyone is one step closer to feeling the love. Oh, I can wait ten years for love. Can't you? Now, the question is how long will it be before prototype languages are accepted? I'm betting at least twenty years from now. Well, that's a lot of time to be ahead of the curve and kicking everyone's butt don't you think?

Thursday, August 25, 2005

Service Provider Went Nuts

If anyone sent me email today and I haven't replied, please resend it. My service provider's email server went nuts and I know I lost some email, but I don't know how much. So, if you don't have a reply from me, I'm not ignoring you. Thanks!

Wednesday, August 24, 2005

Amen, brother

Sam Tesla has a simple prayer that we should all say several times everyday. Right on!

I, Prototype

...unfortunately, Self was not the last object-orientedprogramming language. Self does have some claim to be the lastinteresting object-oriented programming language, or at least the lastinteresting modern OO language with most languages coming afterwards,C++, Java, C#, Cb, being as distinguisable as Coke from Pepsi orMalboro from Rothmans: you dont drink the drink, you drink theadvertising (Twitchell 2000). In Self, at least you can hear yourselfscream.

I must admit that I agree. The above quote is taken from the paper, Attack of The Clones.It's a paper that shows some of the patterns from GoF book implementedin Self. It has to be one of the best reads I've come across. It'scertainly entertaining. Here's some more:
Anotherlovely, natural example of dynamic inheritance in Self. You could dosomething almost as nice Smalltalk using doesNotUnderstand but theSmalltalk Companion doesnt talk about it because, well, theyre wimps(Alpert et al. 1988). You can also do exactly the same thing inSmalltalk using Wrappers (Brant, Foote, Johnson & Roberts 1998).

TheSmalltalk companion is one of my favorite books and I wouldn't callthem "wimps", but it just made me chuckle. And I can't forget this one:
How hardcore do you want to be?
How many lifetimes to you want to waste?

Idon't want to be hardcore and I'm tired of wasting lifetimes...=) Thisarticle is just another one that is making me fall in love with Selfand prototype-based languages more and more. I can't wait to implementand play with these in Io.

Monday, August 22, 2005

Bob Moog Dead at 71

It's sad when your heros start dying. Moog synthesizers are known around the world as being the best. Moog was one the first electronic instruments makers (apparently, he was inspired by what he saw at Raymond Scott's house). He started out making Theremins which are the things responsbile for all of those eerie sounds in 50's horror and sci-fi movies. He's been such a fixture and icon in electronic music. I'm so shocked. I was hoping to meet him one day and thank him for all of the good that he put into the world. Love is lots of knobs and flashing lights to make wonderful sounds. He was the inventor and catalyst for it all. He will be missed. I'm going to go plug my mooger foogers in right now and play in remembrance. Why can't the good ones live forever?

Shameful and Unprofessional

Iron Maiden was pelted with eggs at their last show of Ozzfest. Here's a personal account taken from Blabbermouth:
The manager of a well-known heavy metal band (*NOT* IRON MAIDEN) who attended this past weekend's Ozzfest show at the Hyundai Pavillion in Devore, California has submitted the following first-hand account of the evening that will surely go down as one of the most shameful moments in recent rock history (NOTE: at his request, the author's identity is being protected by BLABBERMOUTH.NET):

"Saturday night's Ozzfest at the Hyundai Pavillion near Los Angeles was a debacle on so many levels, I am still in shock as I write this. As a fan of many of the bands [Saturday] night, one can only hope this was an isolated incident, but sadly, it most likely wasn't. As many of you have heard already, co-headliners and metal legends IRON MAIDEN were pelted with eggs, bottle caps, beer cups, spit on, had people from the Ozzfest camp talking over the PA during their set, had 'Eddie' delayed from his onstage entrance, had members of the [BLACK LABEL SOCIETY] entourage rush the stage with American flags, and had the PA intentionally turned off over 6 times, all by the OSBOURNE CAMP.

"While it's still unclear as to the exact reasons why the terrorizing started (rumors abounded as to why, with everything from Bruce calling out Ozzy in the U.K. rock magazine Kerrang! on the widely known fact that Ozzy uses a teleprompter, to various vague references said on stage about a 'reality show' at an Ozzfest stop in Detroit), one thing was very clear: The whole thing stunk, and left me, and nearly all of the 40,000+ heavy metal fans in attendance angered and disappointed. Not that behind the scenes bickering or magazine trash talking is anything new to rock fans, but the shocking lack of professionalism at one of the largest stops in North America in front of 40,000 + spectators, at the hand of the Osbournes was nothing short of disgusting.

"It all began early in the afternoon, when many side stage bands were openly approached in clear view of everyone backstage by Sharon and Kelly Osbourne to 'join them in throwing eggs at IRON MAIDEN this evening.' All the bands were encouraged to rally the other side stage bands to do so. Members and/or friends of the hardcore band BURY YOUR DEAD were seen actively trying to encourage other side stage bands to 'join in the fun.' Thankfully, many side stage bands angrily declined.

"Later that evening, as IRON MAIDEN came on stage, their intro was interrupted by [BLACK LABEL SOCIETY] hanger-on and biker wannabe Big Dave, who was at the soundboard loudly chanting 'Ozzy, Ozzy' over the PA. MAIDEN opened their set and the entire band was pelted from the front row with eggs, beer, beer cups, spit, and various other objects by an Ozzfest-credentialed, bandana-wearing, Osbourne entourage. IRON MAIDEN, ever the professionals, continued through their set, and by the time they launched into their second song, 'The Trooper', Bruce changed into a civil war-era, red coat and began waving a Union Jack — British flag. Then, someone in, or associated with, BLACK LABEL SOCIETY tried to rush the stage waving and American Flag with the words 'Don't fuck with Ozzy' scrawled across his bare chest. He was tackled and beaten by MAIDEN crew and promptly thrown off stage.

"As 'The Trooper' ended, frontman Bruce Dickinson, with characteristic spunk, launched into a scathing attack on the people terrorizing his band, calling them 'a sorry excuse for an Ozzy Osbourne fan,' and wondering aloud how, 'three dozen eggs could get snuck into the front row of Ozzfest by people with Ozzfest laminates?' Though he never named names, all in attendance could understand who he was referring to. Nicko McBrain ran up to the front asking Bruce to hold on while he cleaned egg off his drums. He then stated the the next song wouldn't be heard on 'Your local cocksucking corporate radio station, wouldn't be seen on MTV anymore, and sure as hell wouldn't be played on a fucking reality TV show,' met by a huge roar from the crowd.

"During the song 'Hallowed Be Thy Name', Bruce, after only the first two lines, stopped singing and ran to the front row, firing back at his terrorizers, saying 'That asswipe right there, with the curly hair, the fucking glasses, and Ozzfest laminate throw his fucking ass out of here right now. It's gonna take more than eggs to stop IRON MAIDEN, and if it wasn't for a lawsuit, I'd rip your fucking head off right now, you piece of shit!!!!' He had the various attackers ejected and continued with a blistering version of the song until right before the big sing long at the end, the PA was INTENTIONALLY cut off. When it came back, Bruce launched into another scathing attack saying that they were supposed to play a shorter set than normal today, and only play 55 minutes, but IRON MAIDEN can't drive 55, or play 55, and were going to play our whole fucking set tonight.

"The band endured six more 'PA cuts,' including having the power to their amps turned off at one point. When the PA would come back on, they would simply launch into the next IRON MAIDEN classic, never missing a beat. Frankly, with every PA cut, the band just got meaner and meaner, playing each new song with an anger and a fire that was at times, simply astonishing to watch. Bruce began the introduction to IRON MAIDEN with a speech about 'Your constitution has something about 'We The People.' Well let me tell you, the only reason we are up here tolerating this bullshit, is because of you people. You have been amazing Glen Helen, and there are A LOT of IRON MAIDEN fans here tonight,' eliciting a huge roar from the crowd. He continued, 'It's gonna take more than eggs to stop IRON MAIDEN, NOTHING is going to come between us and our fans, and it will be death before dishonor, this is 'Iron fucking Maiden',' which was greeted by a thunderous applause. During 'Iron Maiden', longtime MAIDEN mascot Eddie was purposely delayed from making his entrance, making a brief appearance at the end, and one could only wonder as to how. As the band closed there set with a furious version of 'Sanctuary', the PA was again cut only to have Big Dave repeatedly chant 'Ozzy' over the PA, while the band tried to say goodbye to their fans. The now-furious crowd angrily drowned him out with chants of 'MAIDEN, MAIDEN.'

"Then, not 10 seconds after MAIDEN left the stage, Sharon Osbourne walked on stage and predictably, tried to give MAIDEN some fake, half-hearted praise about how they'd like to 'thank IRON MAIDEN,' and what a wonderful band IRON MAIDEN are, and how their crew were 'fantastic,' then sneering, 'But Bruce Dickinson is a prick.' The entire crowd, now fed up with the entire affair, began loudly booing her, pelting her with beer cups, and yelling 'bitch.' She tried to carry on, adding that 'Bruce had disrespected Ozzfest,' only to be drowned out by an ocean of boos, and soaked with beer. She slammed the microphone down and stormed off stage. Many in the crowd, fed up with what they had just witnessed, especially considering that many had come solely for MAIDEN, and paid upwards of $150 to do so, left in droves. SABBATH played to maybe half the audience that was there prior, and seemed stagnate compared to the band preceding them. As a huge fan of SABBATH, I honestly couldn't stand to watch them.

"I've seen IRON MAIDEN probably 10 times in my life, and frankly this was the very best IRON MAIDEN show I've had the pleasure of witnessing. You DON'T want to fuck with IRON MAIDEN. The more the Osbournes tried to fuck with them, the better they got! IRON MAIDEN was on fucking overdrive! Considering the amount of terrorizing and intimidation that IRON MAIDEN had to deal with at the hands of the Osbournes and the other side stage and main stage bands participating, they were the consummate professionals. They had the crowd in the palms of their hands, and IRON MAIDEN and Bruce Dickinson proved beyond a shadow of a doubt why they are the greatest metal band on earth right now, and quite possibly, the classiest, too.

"The Osbournes are drunk with power. Shame on them, and shame on ANY of the bands that participated in the terrorizing and intimidation. It was disgusting display, that NO BAND should have had to endure, but especially a legend like IRON MAIDEN. That fact that it happened in front of 40,000+ people, at a Clear Channel-sponsored event, while Hyundai Pavilion Security turned a blind eye and let the Osbourne camp pelt one of the main headlining bands with eggs, beer, and spit, was simply inexcusable.

"I will proudly be attending next year's MAIDEN fest, and as much as I hate to say it, I can't bring myself to spend another dime on the Osbournes.

"Ozzfest, hang your head in shame."

Indeed...I can't believe this happened. This takes unprofessional to a whole new level. I have new found respect for Maiden for putting up with so much crap. And if it is true that Sharon had anything to do with it, I might have bought my last album of any of the bands involved and seen my last Ozzfest. I can't express how unmetal and deplorable this was. Up the irons.

Fly On The Wall

I wish I could be a fly on the wall at the Vancouver Lisp User's Group when Avi gives his Seaside talk. I think it would be not only a fun talk, but I would love to hear the resulting conversations. Avi has taken the basic continuation-based web server that started in Lisp and has taken it much further. The suggestions of Lispers would especially be interesting. Makes me wish I lived in Vancouver.

Team Design

I was reading "The Cognitive View: A Different Look at Software Design" by Robert Glass. And the following quote struck a chord with me:
Those same researchers have been looking into team design. And
they’ve found that, in many ways, it’s a shared form of individual
design:
  • The teams create a shared mental model.
  • Team members, sometimes in their own minds and sometimes in the group, run simulations against the shared model.
  • The teams evaluate the simulations and prepare the next level of the model.
But in some ways these efforts are unlike individual design:
  • Conflict is an inevitable part of the design process. It must be managed rather than avoided.
  • Communication techniques become a vital part of the design process.
  • Issues sometimes "fall through the crack" because no individual claims responsibility for them.

I'm always preaching about a "common vision" on the teams that I'm on and I always feel strongly about obtaining it. All of the successful teams that I've been on have had this "common vision". It's a shared goal and reaching for the same target. Without it, every individual has what they think the design should be and you end up with an unmaintainable big ball of mud. It's his first bullet point! A well-oiled agile team achieves all of the first bullet points and knows how to manage the last set. In fact, the last set of bullet points really boils down the problem of unsuccessful teams well. Healthy conflict resolution is paramount to a successful team. Mr. Glass goes on to define what a consider to be the definition of a good IT manager:
In managing design, managers can focus on communication facilitation and conflict resolution as their contribution to design. The empirical studies researchers further suggest that management of design should be the management of the key issues that arise during the design process.

The manager's job should be removing obstacles from the software designers and coders and not standing over you make sure you get your job done. If as a manager, you have an employee that you have to stand over to get their job done, then you've hired the wrong person. You should be making sure your developers have a proper road to race toward the goal on.

There's a lot of nuggets of information contained in and all in all a good read.

Dynamic Languages Help You Design

Darrell Norton makes some interesting observations from "The Cognitive View: A Different Look at Software Design" in his blog entry, Dynamic languages work closer to how you design software. He combines points from this article with the one I mentioned earlier. All three articles are worth a read. I especially love this quote at the end of Darrell's blog entry:
"when I want to focus on the domain problem and not the implementation in curly braces, End If's, or angle brackets, dynamic languages are a (good) answer."

Why REPL is a good thing

Here's a great article on why REPL (read-evaluate-print loop) is a good thing. He mentions using IronPython for .Net, but you can get the same functionality in java with Jess, Groovy, jRuby, and of course, jPython. I love the mentions of Smalltalk. REPL allows you to try out designs and code out quickly. Smalltalk compiles code when you save and you never notice it. One thing that people don't realize is that you are inside a running system that you can change. Any change you make to the system is live, it's not operating on a dead instance of the system. It's the same functionality that gets blank stares at "Ruby On Rails" demos. Sad thing is we've had this for over 20+ years in Smalltalk and Lisp. I'm just glad our industry is finally coming around.

Sunday, August 21, 2005

Cool Pavement Drawings

Juian Beever is a pavement artist that does great work. Check out his website and go down to the 3D illusions gallery. INCREDIBLE! Here's one to whet your appetite:



I would probably walk around that if I saw it! Great optical illusions. MAD FUN!

Saturday, August 20, 2005

Kent Beck vs. Alan Cooper

My friend, Larry Brodahl, sent me a classic article debating Extreme Programming vs. Interaction Design from both of their visionaries. I would love to see more debates like this. I wish they would have continued this discussion. It felt unfinished. It was a great debate! We should always be interested in doing things better. And that is what these types of discussion allow. They make us look at what we are doing and question what is not working.

By the way, if you have never read "The Inmates Are Running The Asylum", you need to now! I can't wait to read "About Face 2.0" now.

Friday, August 19, 2005

Object Inheritance

I've long been a fan of "Streamlined Object Modeling". It's a book I keep coming back to over and over. I was reading it recently and wondered why I never noticed the connection with prototyped delegation and what they call "object inheritance". The book is a collection of domain modeling patterns and several use "object inheritance". One pattern in particular expresses the relationship between an actor and a role. For example, let's look at some java code:
/**
* The common behavior of the actor and the role
*/
public interface PersonProfile {
public String getName();
public void sendEmailTo(EmailAddress another, String message);
}

/**
* The actor's behavior
*/
public interface Person extends PersonProfile {
public void setName(String aName);
public void setEmail(EmailAddress anAddress);
}

/**
* The role's behavior
*/
public interface Employee extends PersonProfile {
public BigDecimal getSalary();
}

The implementation is not important. I wanted to show example interfaces and to show the relationships. The point to object inheritance is that the Employee forwards the calls for PersonProfile on to a Person that it holds on to. This allows you to pass around the role or actor through the same interface. Now, you might be thinking that's a lot of forwarding going on. It is. Now, you could get fancy by using a Proxy and an InvocationHandler. In fact, I do something similiar in Smalltalk when I compile the forwarders on the fly. It's a great modeling technique and is useful in several contexts for expressing clarity in the model. Prototype programming languages make this modeling technique easy to implment (no duplication or coding gymnastics required) by the use of traits. Simply put, traits is a composition technique to combine collections of behavior with data to construct objects. To learn more about traits, read the paper, Organizing without Classes.

The good news is that it's simple to do this technique in Smalltalk by use of the Traits package. Ruby even has it through its Delegate framework. Once you start thinking in Traits, it's hard to go back. Have fun with this new technique and happy coding!

"Streamlined Object Modeling" has the best discussion of modeling and implementing business rules in object-oriented languages that I have ever seen as well. It's a great book all around that balances theory and implementation. It's filled to the brim with great advice that every business modeler should know.

Thursday, August 18, 2005

More Good News

It seems BEA is looking at scripting languages to add to its arsenal of products. It seems dynamic languages are making all kinds of head way in the world. ROCK!

SmallHttpUnitTest Rewrite Update

After finally fixing SmallHttpUnitTest for VisualWorks and having talks with several folks at Smalltalk Solutions, I felt it was time to revamp SmallHttpUnitTest. For one, it was slightly misnamed in that the tests are really end-to-end acceptance tests. I was trying to make the navigation easier through the objects. But, somewhere I made a wrong turn. I started to really look at the Selenium Testing Framework. It runs your tests in the browser via Javascript. Nice. It's simple and it works with a nice a table structure like FIT. You can even command it remotely from another language as well such as Smalltalk, java, Ruby, and more.

Well, it all got me thinking how nice it would be to drive the browser like Selenium does, but with the nice object traversal that I used for SmallHttpUnitTest. You can command Internet Explorer, Firefox, and Opera via Javascript. It's a slightly different idea from Selenium in that the web page that you're loading does not need to have any Javascript loaded. The Javascript works externally via a script that runs the web browser via COM (for Microsoft) and I'm still researching Firefox/Mozilla (but, I know its possible to drive them with Javascript as well). It would seem some Ruby people had the same idea! But, I want to take it further. Javascript makes a lot of things easy since it is so well-integrated into the browser.

The pieces of SmallHttpUnitTest that are in Smalltalk will be re-implemented in Javascript. A lot of the browser handling code is no longer needed! The Smalltalk piece will be an external application that watches what you do as you're traversing your web application and takes notes. Once you've finished navigating, you could update your asserts for each page load and have Smalltalk generate the Javascript for you. I'm doing the proof of concept for Internet Explorer since I am more familiar with the OLE/COM model to drive IE. But, I expect Firefox to be a no brainer. I should only have to replace one object and everything will just work. So, you could have one script that drives both. There's a few more surprises that I want to work out and I will be blogging about them. I have a lot of work ahead of me. This a completely different approach than what I was thinking of doing at Smalltalk Solutions. I've been slow doing the prototype, but I have been a busy boy!

You might be wondering how I got the DOM searching of HttpUnitTest working in Javascript since it uses generators and doesNotUnderstand: a lot. Well, that's a topic for another blog entry. Let's just say that higher order functions are your best friend.

Wednesday, August 17, 2005

Java's Coolness Declining

It seems Apple is dumping java for Cocoa development. I've felt the java coolness factor on the decline for awhile now and scripting languages on the rise with the developer of Rails getting Google hacker of year. I love seeing dynamic languages getting more of the lime light. It's going to be interesting how Python and Ruby will change developer's perspectives. No matter what, it will be a fun ride.