Tuesday, May 27, 2008
Yet Another Seaside Talk
Monday, May 12, 2008
My Passion
...seeing Blaine’s eyes light up every time he got to either hear or utter a sentence that included the word “Smalltalk”.
To me, Smalltalk defines elegance. If you want to see elegance in computing, go download Squeak right now. The very least that will happen is it will warp your mind and make you a better programmer. It might even make you see the world a little differently.
Seaside Presentation
Friday, May 09, 2008
Seaside at Bar Camp Kansas City
Friday, April 04, 2008
Monkey Patching
The main reason monkey patching is so dangerous is the global change it makes and the increased probability of having a collision if another project names a method the same. Or worse, another project overrides the default behavior and replaces it with their own. Both can cause subtle bugs that can be hard to catch and find. It's the global nature of it that can bite. It's convenient, but you should think twice before doing it. It's limits your project's options.
Groovy has a novel approach to monkey patching in that it allows them to be scoped for the duration of a block called categories. This reduces the risk of a global change and the addition is only in affect for the duration of the block. Now, it can cause issues if something gets called outside of the block by accident, which is why I wish it had different ways of scoping (class, package, etc). But, with AspectJ these problems can be reduced. Categories reduce a lot of the risk of monkey patching in that collisions are highly unlikely and the protocol is only widened for that invocation. It also ensures that unknown project dependencies will not creep in. I worry less about monkey patching in this instance because if you get burned, it will be your project not everyone else. I think categories are the way to go (if they added class scoped categories, I would be in heaven).
I don't hate monkey patching. Far from it. It is handy to override method implementations during debugging. I can change pre-existing methods if they have bugs in them even before the next release is out. I don't have to wait on the vendor. These are great pluses. I'm just advocating thought before you monkey patch in your own projects. Much like before you swing the inheritance hammer, you should do the same with monkey patches.
Tuesday, April 01, 2008
What's that Squeaking in Omaha?
Saturday, January 05, 2008
Reflection on Everything
One thing you have to be careful in dynamic languages are message not understood or method missing errors. One easy mistake to make is to do the following:
[someObject doSomething]
on: MessageNotUnderstood
do: [:ex |
"log something"
^self]
What's wrong with the above code? Well, are you trying to catch if doSomething is not understood by someObject? If so, the call can still succeed and there could be a nasty bug further down in the code. The handler will be giving misinformation on the true problem. Frustrating to say the least. It's better to do something like this:
[someObject doSomething]
on: MessageNotUnderstood
do: [:ex |
(ex message selector == #doSomething and: [ex receiver == someObject])
ifTrue: ["log"
^self]
ifFalse: [ex pass]]
Yuck. But, it does check the receiver and selector to make sure we captured the right exception. Lots of typing for something simple. Granted you shouldn't be doing a lot of guarding against MessageNotUnderstoods (polymorphism anyone?). But, sometimes it is necessary. Besides, we wouldn't have this fun little blog post would we. Basically, the above method checks for the right selector and receiver that we expected to have a MessageNotUnderstood and if it did we do our logging code. If not, it's something we didn't account for and is a bug, thus we "pass" the exception to the next handler. But, how can we prevent ourselves from all of this typing?
Squeak has this method implemented:
BlockConext>>onDNU: selector do: handleBlock
"Catch MessageNotUnderstood exceptions but only those of the given selector (DNU stands for doesNotUnderstand:)"
^ self on: MessageNotUnderstood do: [:exception |
exception message selector = selector
ifTrue: [handleBlock valueWithPossibleArgs: {exception}]
ifFalse: [exception pass]
]
It does not check the receiver, but that's OK. It turns our code into this:
[someObject doSomething] onDNU: #doSomething do: ["log something" ^self]
Nice. It's much more succinct, but I don't like the duplication of "doSomething". What are we to do? I came up with this method:
BlockConext>>onImmediateNotUnderstoodDo: anExceptionBlock
^ self
on: MessageNotUnderstood
do: [:problem |
| myContext problemContext |
myContext := thisContext home.
problemContext := problem signalerContext sender sender sender.
(problemContext == myContext
and: [self method messages includes: problem message selector])
ifTrue: [anExceptionBlock
valueWithPossibleArgs: (Array with: problem)]
ifFalse: [problem pass]]
Here's what it makes our code look like now:
[anObject doSomething] onImmediateNotUnderstoodDo: ["log something" ^self]
It looks like what we started with, but this version is safe. It will pass the MessageNotUnderstood exception if the send did not happen directly from the block we defined.
What is the method above doing? The method I wrote reflects on the stack and the compiled code. I use the stack to find the receiver that should be in the block. The compiled code is needed to find all of the selectors that are called directly from the block. Pretty cool, huh?
Smalltalk is one of the few languages where you can reflect on everything on the stack. Stack frames are objects too. It makes doing difficult things possible.
Sunday, November 11, 2007
A Happy Diversion
Another idea came to me. The tab for my Monticello flap was boringly called "Monticello". What a waste of real estate. My second problem was that I'm always getting confused at which project I'm in. I normally use different background colors to make it easy. But, I still get confused. I was blessed with a small brain. I curse it everyday. What is a poor little Squeaker to do? I thought I could put the name of the current project on the Monticello tab instead of the one it has. I wondered how hard would that be? And off I went...
How can I do that? I could change the tab name when the project changes. Eureka! That's what I will do. I remembered I wrote a little utility to change background images and I had to know when the current project changed. I started my hunt there and event handlers are available via the morphic world to know when a project is entered or exited. We only care about when a world is left. Why? The event handlers has to be registered on the world itself and we don't want to have to keep track of every project and world. It's easier to put a handler on the current project and know when it is left.
Let's start with this method for setting the world we're currently in:
world: aMorph
world == aMorph ifTrue: [^ self].
world ifNotNil: [world removeActionsWithReceiver: self].
world := aMorph.
world ifNotNil:
[self changeTextOnTab.
world
when: #aboutToLeaveWorld
send: #leavingWorld
to: self]
Basically, this method removes all events from the old world since we will not care about it any longer. Then, we change the text on our tab and add our event handler. Next, how do we change the text on the tab? In the menu for a tab, is an item to change the name of the tab. Using the handy morphic handles, I inspect the menu item itself and find the method it will call when it is invoked. Here's the code I came up with:
changeTextOnTab
self monticelloFlapTab ifNotNilDo: [:tab | tab changeTabText: Project current name]
The simple method changeTabText: does all of the magic. We just get the name of the current project. I haven't showed you how to get the tab itself. I look through the methods on the class side of Flaps to reveal its magic:
monticelloFlapTab
^Flaps globalFlapTab: 'Monticello'
The good news is that it will always find the flap this way no matter the name. The only thing left is to what to do during the handling of leaving the current world. The dilemma now is how do we know the next world? Some more digging and we can be ask ed to be called later. Perfect. Here's the code for the handler:
leavingWorld
WorldState addDeferredUIMessage: [self world: Project current world]
And that's it! The same method can be called to seed our initial world as well. Now, a quick glimpse to the bottom of the screen gives my project name. Easy. Now, I can get back to updating my Seaside presentation.
Why I Love Squeak
addMonticelloFlap
| newTab monticelloBrowser |
newTab := Flaps newFlapTitled: 'Monticello' onEdge: #bottom.
self currentWorld addMorphFront: newTab.
newTab adaptToWorld: self currentWorld.
Flaps addGlobalFlap: newTab.
newTab showFlap.
monticelloBrowser := MCWorkingCopyBrowser new.
(monticelloBrowser window)
openInWorld: newTab referent extent: monticelloBrowser defaultExtent;
topLeft: newTab referent topLeft + (10 @ 10).
newTab referent height: monticelloBrowser window height + 20.
newTab hideFlap
The above code snippet adds a new global flap to the Squeak environment. Inside the flap is the Monticello browser. I've been doing this in my Squeak images for a long time, but doing the above by hand for each image. I went into the system and figured out what each of the menu items did to create the above. This is simple in Squeak because everything in Morphic is inspectable. It allowed me to create the script you see.
The reason for having a Monticello browser in a global flap is so that you can always have it open in every project and easily accessible. I like to have a Squeak project for everything I do and like having one Monticello browser.
The above was not much effort and took little time to figure out. Love is.
Thursday, October 18, 2007
Debuggers...again
Why? Well, it depends on what I'm doing. I use the debugger for exploratory programming, when sinking into the depths of someone else's code (especially if they didn't write tests), during code reviews, and when faced with a nasty bug. Even though I write my code in small pieces (small classes and small methods), I am not perfect. When everything is combined and put into production, strange things happen to my code. The code doesn't change; the environment does. A situation occurs that I didn't think of and thus it is not tested. This is the realm of the debugger especially if the bug is nasty and hard to find. Any piece of complex software has these hidden. We are human. Let's embrace that. A world without debuggers is a weird sci-fi perfect world with monsters lurking beneath the surface.
Debuggers are great for exploratory programming when you are just trying out a new framework and seeing how it works. I like to walk line by line. I did this when I was learning Seaside and it was better than any documentation. Besides, watching beautiful code unfold in your debugger is nothing short of reading a great book. And when you're dealing with some ugly code, a debugger has shown me things that my eyes deceived me on when just looking at the code. Why dissect the dead animal when I can see how its organs work while it is still alive?
An expressive debugger saves time as well. I remember when I came back to Smalltalk after doing Java for several years. I had forgotten that you never need to restart your programs. I wrote a simple Seaside application and only restarted the web server once. I coded live in the system and when I saw a problem (that my tests didn't catch) in the debugger, I could change it right there. It was amazing.
I guess all of this talk of no debuggers or that debuggers is a crutch for bad developers. It can enable the "get it running once" mentality instead of thinking of all the cases and your design. Like any tool it can be abused, but that doesn't mean we should get rid of all tools. Duck typing can be abused as well and I wouldn't trade it for the world.
Monday, September 10, 2007
We Need Each Other: Ruby and Smalltalk
I'll start with a quote from Neal Ford:
the Smalltalk version is a great example of accidental complexity, not essential complexity.
There is no example given of what the "accidental complexity" was in Smalltalk. But, let's look at an example that Rubyists are familiar with and then I'll go forward:
class Person
attr_accessor :name
end
This will generate the accessors :name and :name= at run-time. It's a nice way to describe a public field. There's even read and write only variations. It allows you to describe your intent of the field. Now, in Smalltalk you could do the same thing with class-side methods. Like so:
attributeAccessors
^#(name)
This could add the instance variable (if it didn't exist), and generate the getters and setters when the class is initialized. It is true in this case, we would use tools to do the generation and generate the code before hand. I think this is what Neal was talking about accidental complexity because we are adding methods that we later have to browse through. But, this is where they are mistaken.
Smalltalk has categories and usually, these code generated methods are placed in them. Accessors are generally placed in their own category so do not add to the cognitive friction. In fact, when I use code generation, I group the methods in a category with "AUTO" in it. This is so that I can later delete those methods and start over. Also, it allows me to not have to look at them when looking at the more important methods of the class.
There is one last way to do things like this in Smalltalk, but is rare. Classes are created in Smalltalk by sending messages. It's not some hard-coded construct in the language. It's a message. We can create our own messages to create our own classes. Here's what the example could look like in Squeak:
Object subclass: #Person
attributeAccessors: 'names'
classVariables: ''
poolDictionaries: ''
category: 'MetaExample'
And lastly, there is a initialize method for all Smalltalk classes that would give a more Ruby feel:
initialize
self attributeAccessors: 'name'
Now, with all of that said, these are just examples to show what is possible. It's all a matter of taste and what you are trying to accomplish to which method you choose.
finally, my mouth dropped when I saw this in the same blog post:
Smalltalk had (and has) an awesome environment, including incredible tool support. Because the tool is pervasive (literally part of the project itself), Smalltalkers generally shied away from the kind of meta-programming described above because you have to build tool support along with the meta-programmed code. This is a conscious trade off. One of the best things about the Ruby world (up until now) is the lack of tool support, meaning that the tools never constrained (either literally or influentially) what you can do. Fortunately, this level of power in Ruby is pretty ingrained (look at Rails for lots of examples), so even when the tools finally come out, they need to support the incredible things you can do in Ruby.
I will answer this as bluntly and respectively as I can. Smalltalkers have NEVER shied away from meta-programming because of having to build a tool. Most Smalltalkers have a bag of tools that they use and add to their environment. Tools are so easy to write in Smalltalk that most programmers in it have at some point written one or two to help them. It's trivial to add functionality to the browser and inspectors. Generally, Smalltalkers only stay away from things that are hard to debug (ala method_missing, doesNotUnderstand:), but do them when necessary. Readability is always the utmost importance to Smalltalkers. Abbreviations are generally frowned upon even.
The last thing I want to remark on is the quote in bold above. I'll repeat it here because it makes me both shocked and sad:
One of the best things about the Ruby world (up until now) is the lack of tool support
I hardly call that a strength. Really. Why would I want to go back to bear skin and stone development? I have finally become productive in Java because of Eclipse (code browsing, auto-format, code completion, refactoring, etc). Why would I want to go back to command line brute force methods? I keep hoping for a great Ruby IDE (some are close like Ruby's Eclipse plug-in, Arachno, etc). Besides, I think while tools like ri and rdoc are nice, I want to look at source code and it's difficult to find the definitions of methods (without using grep) when going through new source code. A friend once told me he never trusted a language you couldn't write an IDE for it. There's truth to that. I never got FreeRIDE to last longer than a few minutes of development. Tools and easy to read syntax are necessary.
Ruby has great potential, but the syntax needs to be heavily reafactored (%w while being nice shorthand is unreadable) and made more consistent (blocks do not take the same types of arguments as methods, I can not send a block with & into a block example, lambda {|&block| block.call } gives a compile error). But, those are my gripes and I do still like Ruby. I think boasting that your language has no tools is short sighted at best.
I think both Smalltalk and Ruby developers could learn a lot from one another. So, if any Ruby developer has questions about Smaltallk, please feel free to email me. I will even extend the same to Smalltalk developers curious about Ruby. The point of this post was mainly to educate and inspire both Rubyists and Smalltalkers to be better.
Saturday, August 11, 2007
My Favorite Smalltalk is Gone
I realize it's hard to make money in the software development tools business. My own business failed as well. I was hoping for Dolphin to stick it out. Good luck to the Dolphin guys. I just want to thank them for all the love they put into the world. Dolphin will always have a special place in my heart. It will be hard to say good-bye.
Well, there's no reason for me to stay with Windows anymore now.
Sunday, July 08, 2007
Smalltalk Obstacles
- Different World Image-based development is strange to most developers. Also, Smalltalk forces developers to drop all of their pre-existing tools to play in this magical world. It's a lot to give up.
- Different Syntax Smalltalk's syntax baffles a lot of developers because it's so different from anything else. Most of what they have seen has been Algol-based. But, I've never seen a developer not understand it within a few minutes, but it is a hurdle for folks. This hurdle will always be there. Changing the syntax would make Smalltalk not Smalltalk.
- Unwillingness to compromise Smalltalk is powerful and the integrated tools is what makes it powerful. But, a little compromise to help developers dip their toes would help. At least allow to have some sort of training wheels before they jump in all the way. We need to allow them to test the waters.
But, the new obstacles along with the old ones are:
- We no longer have the largest library It's incredible the amount of open source libraries that Java and Ruby has. It's especially true for Java. It's enormous. Anything I want and it's been done. From database mapping to GUI to XML to you name it, it's just a source forge click away.
- Dated All dialects besides Dolphin look dated. There's no pizazz and simple things like consistent key bindings are not there. It's all a matter of polish and it shouldn't matter, but it does to a lot of developers. Sad but true. Looks matter.
- Tutorials There has been movement in this area recently in both Squeak and Visual Works. It's great and we need more.
- Marketing All of the Smalltalk web sites look old. Some graphic designers would go a long way. Ruby on Rails got to the top of the heap and exposed Ruby because of great marketing. I was programming in Ruby before Rails and it had none of the benefits of Smalltalk. We have a strong community, but marketing wins. Java kicked our butts once and at the time, we had the best libraries, environment, and everything. Marketing is king.
Now, that being said, I think a better looking Squeak, VisualWorks, and VisualAge is a must. I think they should all look at Dolphin. Dolphin is everything a modern Smalltalk should be. It's gorgeous. The key bindings are consistent, tools are easy to understand, and it's a pleasure to work with. They are also constantly adding new tools to help productivity (IdeaSpace) as well. In fact, I usually show developers Dolphin first to get them interested.
I think a good looking GUI is the first step. But, I also think making it easy for developers to use Smalltalk as a scripting language is a must too. We need to allow for developers to ease into image-based development by using their own tools. Yes, they will be less productive, but consider it to be an olive branch somewhat.
If we are to get more developers interested, we must come a little to them. I tried writing a scripting like environment for Squeak to make it easier for developers outside of Smalltalk to code in a more scripting style. And I keep playing with syntax to keep the simplicity, but also things to developers from the outside more comfortable.
And last but not least and this is a deal breaker: libraries. Seaside is a huge advantage, but we need more libraries that not only do cool things, but practical things as well. We have a lot of growth needed in this area.
The Ruby community has done a great job at showing off what you can do with pure objects and closures. Now, let's make it easy for them to see why an image and integrated tools make your live easier! We need to get off our island and start mingling with everyone. I created the Omaha Dynamic Language User's Group in the hopes to show developers what makes Smalltalk great(along with other dynamic languages as well like Lisp).
Friday, July 06, 2007
Crabs In The Pot
I feel Smalltalkers should stop complaining (about bad marketing, java, ruby, whatever) and start doing. Steve took a bold step forward and I applaud him for that. We need to have more doers and less complainers. So, if you feel marketing of Smalltalk is not up to par, do something! I started a user's group here in Omaha to get interest in dynamic languages. It's been growing larger and larger. The user group has gotten a lot of people interested not only in Smalltalk, but Lisp as well. But, I know I could do more. Steve is an inspiration and incredibly enthusiastic. If we want people to join us, we need to support the group we have now. Feedback is good and welcome, but if you feel you can do better....Well, then DO!
I didn't mean for this come out like I'm being harsh on Ramon. I don't want that. I love Ramon's writing and by having a blog, he is doing. But, I think we need to be reminded our community is small and we need to support one another. If Squeak is ugly, let's do something about it!
I wonder who will write the next tutorial on how to make Squeak look awesome? Whoever it is rock on! And I hope Steve does more tutorials, the laser game is too much fun. It shows how playful and curious Smalltalkers are and that's a great thing.
Friday, May 11, 2007
Truth, Justice, And The American Way
if (transaction.amount) {
transaction.markValid();
} else {
transaction.markInvalid();
}
Nothing wrong here, from the looks of it the code is checking if the transaction has an amount defined and then marks the transaction valid or invalid. Simple right? But, what if an amount is defined and it is zero? You would think the transaction is marked valid right? WRONG! It will be marked invalid because anything that's zero, nil, or undefined in Javascript is considered false.
And that's my beef, why not treat booleans with their own type. Why treat any other value as equivalent? Subtle bugs like the one above are infuriating to me. The simple reason is that they can easily be avoided with a few extra characters.
if (transaction.amount == undefined) {
transaction.markValid();
} else {
transaction.markInvalid();
}
The moral of this story is to code exactly what you mean. Be specific. Don't rely on arcane language features to save a few key strokes. Java and Smalltalk do the right thing and make you use boolean types.
Tuesday, April 03, 2007
The Power OF Smalltalk Compels Thee
Thursday, March 29, 2007
Java VM Puts Shackles On Development Tools
But, this post is not about how foreign Smalltalk is to java developers, but how still in 2007 with dynamic languages finally getting recognition that few people are screaming for the capabilities of a Smalltalk VM. The productivity of Smalltalk owes not only to its dynamic nature, but to its always running and lively IDE. It's a living environment. Objects are alive and not dead. Why are there not other environments that do this? (OK, Lispers, I didn't forget about you...anyone else?) And why aren't these environments in the newer dynamic languages (Ruby, Python, Groovy, etc)? Have the shackles of the java runtime environment ruined us?
Or maybe the problem is just that we are always thinking of runtime and not development time. Java places a lot of barriers in the way of developers in the name of security. Why not have a specific VM purely for development? One that could dynamically load classes and code. One that could take snapshots of the running system and save the state for later. One that could compile incrementally and keep all of the bookeeping in order so that our tools stay snappy. One can dream.
Now, for Ruby and Python, there is no excuse. They have their own VM and why don't they support IDEs to implemented in themselves? Java, Groovy, and Scala have the excuse of the java VM. One of my hopes for Ruby was a Smalltalk-like IDE, but sadly, I don't think it will ever happen. The first step would be not to throw away the source code when they compile.
The thing that makes Smalltalk IDEs so cool is that they are alive. The VM supports object mutability and snapshotting state. The whole IDE is written in Smalltalk and is part of the live development system. You don't have to restart anything to try something out or shut down the everything to run a new tool. It morphs into what you want and let's you do what you want. No shackles.
This is what I want from the new generation of dynamic languages. I wonder how hard it would be to have a development java VM. Hmmm....
Wednesday, January 17, 2007
Java And Simplicity
I believe, simplicity of language is VERY UNDERESTIMATED asset.See, I worked for years with c++. I liked templates, they were
giving me a 'mental satisfaction'. I liked to check generated
assembler, emmited own instructions when not satisfied.But that's not way how programs should be made.
Once switched to java, I apprecitated simplicity of java.
Java followed KISS principle, provided simple language,
simple tools (javac, javadoc, javah ... ).Now, we are loosing this important asset.
Converted c++ programmers ask their templates and operators.
Converted c# programmers ask their properties and closures.
Coverted script programmers want their dose of language sugar.Java creators made java simple - and not simpler then it should be.
We should apprecitate and preserve it (in rational way).
OK, I'm sure that some of the Smalltalkers and Lispers out there either have their jaws on the floor or hurt bellies from laughing so hard. I know I did at first and then it struck me. We have failed. We have failed to educate on what simple can truly be. When I think of simplicity in language design, I think of Self, Smalltalk, Forth, and Scheme. Java wouldn't even come close. But, there's an army of developers out there that haven't seen better and that is sad.
Sure, we could easily laugh at the uneducated, but it's our fault. Instead we should be sharing and telling. I spent time at RubyConf showing off Squeak and have been known to hang out at the local Java user's groups talking all things dynamic. I enjoy showing people the power that's out there and the great thoughts that have preceded us. It's exciting to see Java getting some of these capabilities and programmers demanding them! The future is bright, but there are still some we haven't reached.
Next time, you hear someone call Java simple, don't snicker. Show them something simple. Who knows maybe someday I'll be able to program in Self because it will be the defacto standard. A boy can dream can't he?
Tuesday, January 09, 2007
Great Post On Smalltalk and Parsers
tangent: No Virginia, Smalltalk does not have operator overloading. It simply allows method names using non-alphanumeric characters. These are always infix and all have the same fixed precedence. How can it be so simple? It’s called minimalism, and it’s not for everyone. Like Mies van der Rohe vs. Rococo.
He makes more and it's a great read. I almost got diet pepsi all over my new Mac while reading it. I tend to stand on the same fence that thinks functional and object-oriented programming compliment each other well. I'll even go as far and say they need each other. I ran across this blog because of my recent interest in Self and Factor. Fun stuff!
Wednesday, January 03, 2007
Amen
I’ve also been reading a lot of the relevant academic literature published since the 1970s; for instance, the Lambda Papers and the myriad works of Henry Baker have been particularly inspiring. I continue to be struck by the harsh reality of the often-asserted, but seldom-accepted, truth that most of the great work in software was indeed done very early on, with virtually no further fundamental progress having been made during the past couple of decades.
I'm in the same boat. I'm just so much in awe of early computer science. I've been reading David Parnas's old papers and they are inspiring. It's amazing how much of the old papers we are reinventing. It's fun and mind blowing reading, but depressing that we haven't push the envelopes further. I think it's time to stop being sad and just do it.
Here's my call to arms. Let's take it further and stop whining! Who's with me?! CHARGE! The next generation of computer science starts NOW!