Making the ugly elegant one day at a time
Gerald Jay Sussman
...And So Many More...
05/01/2003 - 06/01/2003
06/01/2003 - 07/01/2003
07/01/2003 - 08/01/2003
08/01/2003 - 09/01/2003
09/01/2003 - 10/01/2003
10/01/2003 - 11/01/2003
11/01/2003 - 12/01/2003
12/01/2003 - 01/01/2004
01/01/2004 - 02/01/2004
02/01/2004 - 03/01/2004
03/01/2004 - 04/01/2004
04/01/2004 - 05/01/2004
05/01/2004 - 06/01/2004
06/01/2004 - 07/01/2004
07/01/2004 - 08/01/2004
08/01/2004 - 09/01/2004
09/01/2004 - 10/01/2004
10/01/2004 - 11/01/2004
11/01/2004 - 12/01/2004
12/01/2004 - 01/01/2005
01/01/2005 - 02/01/2005
02/01/2005 - 03/01/2005
03/01/2005 - 04/01/2005
04/01/2005 - 05/01/2005
05/01/2005 - 06/01/2005
06/01/2005 - 07/01/2005
07/01/2005 - 08/01/2005
08/01/2005 - 09/01/2005
09/01/2005 - 10/01/2005
10/01/2005 - 11/01/2005
11/01/2005 - 12/01/2005
12/01/2005 - 01/01/2006
01/01/2006 - 02/01/2006
02/01/2006 - 03/01/2006
03/01/2006 - 04/01/2006
04/01/2006 - 05/01/2006
05/01/2006 - 06/01/2006
06/01/2006 - 07/01/2006
07/01/2006 - 08/01/2006
08/01/2006 - 09/01/2006
09/01/2006 - 10/01/2006
10/01/2006 - 11/01/2006
11/01/2006 - 12/01/2006
12/01/2006 - 01/01/2007
01/01/2007 - 02/01/2007
02/01/2007 - 03/01/2007
03/01/2007 - 04/01/2007
04/01/2007 - 05/01/2007
05/01/2007 - 06/01/2007
06/01/2007 - 07/01/2007
07/01/2007 - 08/01/2007
08/01/2007 - 09/01/2007
09/01/2007 - 10/01/2007
10/01/2007 - 11/01/2007
11/01/2007 - 12/01/2007
12/01/2007 - 01/01/2008
01/01/2008 - 02/01/2008
02/01/2008 - 03/01/2008
03/01/2008 - 04/01/2008
04/01/2008 - 05/01/2008
05/01/2008 - 06/01/2008
06/01/2008 - 07/01/2008
07/01/2008 - 08/01/2008
08/01/2008 - 09/01/2008
10/01/2008 - 11/01/2008
01/01/2009 - 02/01/2009
09/01/2009 - 10/01/2009
Thursday, September 29, 2005
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:
Wednesday, September 28, 2005
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
On the first visit to your site, I get this:
Mod_python error: "PythonHandler mod_python.servlet"
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
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:
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.
Thursday, September 22, 2005
Tuesday, September 20, 2005
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!
I got a comment from Anand that suggested that I change this code:
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
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:
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
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!
I have to apologize, but I have to pimp "Streamlined Object Modeling" yet again.
Live it, be it, model it! Let the design flow!
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
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):
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.
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'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.
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
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
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:
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.
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 |
And it returns:
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
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!
I still see old world flat file specifications like the following:
I thought I would do something different implement the parser as if I was a Lisper. So, here's what I came up with:
And what does the code look like to parse it? It's even simpler than I thought:
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.
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.
And this generates the following XML:
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
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.
From Steve Dekorte's blog:
The amount to which the program is object oriented has an inverse relation to:
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
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:
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
Taken from the comp.lang.smalltalk.dolphin:
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
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.
My Weekly Top 20 Artists