raganwald
Tuesday, October 30, 2007
  I hate it when comedy contains deep, disturbing insights
See here where Fake Steve Jobs compares Java to Lotus Notes. Flippant. But yet…

Java is two different things: a platform and a language. Both are going to survive for a good long time in BigCo. They too deeply en-snarled in BigCo’s internals to be excised in a single stroke.

And like Notes, Java’s corporate parent isn’t doing so well. No surprise, Java simultaneously commoditizes hardware and operating systems, leaving professional services as the only way to make money from it.

Hopefully, SUNW—oops, I meant JAVA—will continue to do better with Java the language and/or platform than IBM has done with Notes.

p.s. Yes, you (I mean you!) have written great stuff with Java. Why not? You are a programmer, it is a programming language, you can write anything you want with it. And there were people who did good things with Notes in its day. I respect you for it, even honour you for it. But don’t take it personally when I try to look at the big picture and ask where the platform is going and whether it looks like anything we’ve seen before.

p.p.s. I’ve heard from a number of people asking why I am implying that Sun and IBM aren’t doing so well, when they are thriving in a certain sense. I posted the share price for a reason: a privately held company exists for whatever reason its shareholders deem appropriate, such as employing people or building great products. A publicly held company, OTOH, has one and only one overriding mandate: returns for its investors, either through dividends or through share appreciation.

Over the last five years, Sun has done better than IBM. At the moment, 100% better. So if I were a JAVA shareholder, I would want to be very sure that Sun has a business plan to do something differently. And when picking a platform, I want to be sure that its parent isn’t going to wake up one day and ask, “So why are we doing this, exactly?”
 

Monday, October 29, 2007
  Something to consider when someone criticizes your code
Resentment is like drinking poison and hoping it will kill your enemies.
—Nelson Mandela
 

  Zen in the Art of Rewriting
More than a few people have taken the time to write and say that my writing sucks. Folks, hold your applause! It’s true, it does. This distresses me:

Zen Master Ryokan lived in a poor little hut on a mountainside. One moonlight night he came home and found a burglar looking for something to steal. But Ryokan was a hermit who owned nothing.

“Poor fellow,” he said to the robber. “You have come a long way and have found nothing. But I don’t want you to leave me empty-handed. Please take my clothes.” And Ryokan stripped, and handed the clothes to the robber.

“Poor fellow,” said naked Ryokan, going outdoors again when the inconsiderate robber had left, “How I wish I could have given him this wonderful moon.”

I often feel like there is this wonderful moon, these great truths and beauties, and when I write down what I see, when I try to share it, all I have to give you is a tattered robe. How I wish I could give you the feeling I have when I sit in the moon’s silvery radiance. But my weblog… it’s really just a tattered robe. Why is it so bad? Why do I fall so short?

Writing and coding have a lot in common. One of the most obvious similarities is that good writing is rewriting. I don’t just mean “polishing,” I mean sitting down and reorganizing, dropping stuff that really doesn’t work, finding a better organizational structure for ideas, combining a few things that say the same thing… Rewriting is hard work, much harder than writing.

One of the reasons my writing sucks is that I don’t do enough rewriting. Like many software projects, my blog is a prisoner of the tyranny of the urgent. Once a post is basically coherent, I have to choose between rewriting it and getting Real Work™ done, or writing more Nights-and-Weekend™ code written, or even between rewriting an old piece and writing a brand new piece. Far too often, I say the same thing about a new post that we all say about our software: “It’s good enough, it works, don’t rewrite it, don’t refactor until we need to.”

It’s amazing. We agonize and debate and twist ourselves into intellectual knots over whether a new language or a particular DSL or even a hack makes each line of code easier or more difficult to read. But where’s the emphasis on writing and rewriting each line of code until it’s perfectly readable?




Zen Shorts is a tremendous children’s book, featuring the enigmatic Panda Stillwater and the stories he tells to help children understand their lives. It contains three of my favourites including The Robe and The Moon and The Monks and The Lady.

There’s some sort of fetish for small vocabularies in our industry. This idea that if you use simple words and simple sentences, clear writing necessarily follows without further effort. This is like assuming that the smaller your vocabulary, and the simpler your sentences, the more you write like Hemmingway.

If reading code is far more important than writing it, if we really ought to be writing code for those who come behind us to maintain it, why are we talking about the difference between .map { |x| x*2 } and .map &'*2' when we ought to be talking about the difference between taking two hours to write some code and six hours to write, rewrite, and rewrite the code again?

Is it—I am speaking from my heart here—because languages and tools are glamorous? Because they are the stuff of ideas and intellectual valour? Where rewriting is just plain hard, hard work? Work that few appreciate, because the work of rewriting is “invisible” in the finished code?

In my essay about still failing, and again in my essay about bricks, I lamented the fact that what we can observe about projects and about code is only indirectly related to what is important. Rewriting is one of those things. You can look at code and say, “The Visitor Pattern adds needless cruft.” But how do you look at code and see whether this is the best that can be done? How do you know whether the author banged it out in one go or spent days making it as simple and direct as possible?

Getting back to the story of The Robe and The Moon, there is no doubt that shipping things that just work puts software into the hands of people that need it, just as Ryokan gave his robe to the burglar. But how distressing that we still fall far short of what we could be shipping, of what we could share with the world.

Yes, I admit that my writing sucks. And worse, I admit that much of the code I’ve written in my life sucks in exactly the same way. And I’m going to do better.

I’d like to start now. But first I have to get back to work.
 

Saturday, October 27, 2007
  String#to_proc
Breaking news! The irb enhancement gem Utility Belt includes String#to_proc

String#to_proc is an addition to Ruby’s core String class to enable point-free hylomorphisms

I’ll start again. String#to_proc adds a method to Ruby’s core String class to make lots of mapping and reducing operations more compact and easier to read by removing boilerplate and focusing on what is to be done. In many cases, the existing black syntax is just fine. But in a few cases, String#to_proc can make an expression even simpler.

String#to_proc is a port of the String Lambdas from Oliver Steele’s Functional Javascript library. I have modified the syntax to reflect how String#to_proc works in Ruby.

We’ll start with the examples from String Lambdas so you can see what is actually going on. Then we’ll look at how to use the & coercion to make working with arrays really simple.

to_proc creates a function from a string that contains a single expression. This function can then be applied to an argument list, either immediately:

'x+1'.to_proc[2];
→ 3
'x+2*y'.to_proc[2, 3];
→ 8
or (more usefully) later:

square = 'x*x'.to_proc;
square(3);
→ 9
square(4);
→ 16
Explicit parameters

If the string contains a ->, this separates the parameters from the body.

'x y -> x+2*y'.to_proc[2, 3];
→ 8
'y x -> x+2*y'.to_proc[2, 3];
→ 7
Otherwise, if the string contains a _, it’s a unary function and _ is name of the parameter:

'_+1'.to_proc[2];
→ 3
'_*_'.to_proc[3];
→ 9
Implicit parameters

If the string doesn’t specify explicit parameters, they are implicit.

If the string starts with an operator or relation besides -, or ends with an operator or relation, then its implicit arguments are placed at the beginning and/or end:

'*2'.to_proc[2];
→ 4
'/2'.to_proc[4];
→ 2
'2/'.to_proc[4];
→ 0.5
'/'.to_proc[2, 4];
→ 0.5
’.’ counts as a right operator:

'.abs'.to_proc[-1];
→ 1
Otherwise, the variables in the string, in order of occurrence, are its parameters.

'x+1'.to_proc[2];
→ 3
'x*x'.to_proc[3];
→ 9
'x + 2*y'.to_proc[1, 2];
→ 5
'y + 2*x'.to_proc[1, 2];
→ 5
Chaining

Chain -> to create curried functions.

'x y -> x+y'.to_proc[2, 3];
→ 5
'x -> y -> x+y'.to_proc[2][3];
→ 5
plus_two = 'x -> y -> x+y'.to_proc[2];
plus_two[3]
→ 5
Using String#to_proc in Idiomatic Ruby

Ruby on Rails popularized Symbol#to_proc, so much so that it will be part of Ruby 1.9.

If you like:

%w[dsf fgdg fg].map(&:capitalize)
→ ["Dsf", "Fgdg", "Fg"]
then %w[dsf fgdg fg].map(&'.capitalize') isn’t much of an improvement.

But what about doubling every value in a list:

(1..5).map &'*2'
→ [2, 4, 6, 8, 10]
Or folding a list:

(1..5).inject &'+'
→ 15
Or having fun with factorial:

factorial = "(1.._).inject &'*'".to_proc
factorial[5]
→ 120
String#to_proc, in combination with & coercing a value into a proc, lets you write compact maps, injections, selections, detections (and many others!) when you only need a simple expression.

Caveats: String#to_proc uses eval. Cue the chorus of people—pounding away on quad 3Ghz systems—complaining about the performance. You’re an adult. Decide for yourself whether this is an issue. After mankying things about to deduce the parameters, String#to_proc evaluates its expression in a different binding than where you wrote the String. This matters if you include free variables. My thinking is that it ceases to be a simple, easy-to-understand hack and becomes a cyrptic nightmare once you get too fancy.

You know that Voight-Kampff test of yours… did you ever take that test yourself?
—Rachael, Blade Runner


I have been using Functional Javascript for quite some time now, and I use the String Lambdas a lot. However, Ruby and Javascript are very different languages. Once you get out of the browser’s DOM, Javascript is a lot cleaner and more elegant than Ruby. For example, you don’t need to memorize the difference between a block, a lambda, and a proc. Javascript just has functions.

However, Javascript is more verbose: Whereas in Ruby you can write [1, 2, 3].map { |x| x*2 }, if Javascript had a map method for arrays, you would still have to write [1, 2, 3].map(function (x) { return x*2; }). So it’s a big win to make Javascript less verbose: code is easier to read at a glance when you don’t have to wade through jillions of function keywords.

Nevertheless, I still find myself itching for the String Lambdas when I’m writing Ruby code. It may be a matter of questionable taste, but for certain extremely simple expressions, I vastly prefer the point-free style. (-3..3).map &:abs is shorter than (-3..3).map { |x| x.abs }.

It is also cleaner to me. abs is a message, especially in a language like Ruby that supports the sending arbitrary messages named by symbols. Writing (-3..3).map &:abs looks very much like sending the abs message to everything in the list. I don’t need an x in there to tell me that.

Thus, I obviously like (-3..3).map &'.abs'. But I like (1..5).map &'*2' for the same reason. It isn’t just shorter, it hides a temporary variable that really doesn’t mean Jack to me when I’m reading the code. And quite honestly, (1..10).inject { |acc, mem| acc + mem } raises more questions than it answers about what inject does and how it does it. (1..10).inject &'+' gets right down to business for me. I’d prefer that it be called “fold,” but the raw, naked + seems to describe what I want done instead of how I want the computer to do it.

Symbol#to_proc also supports named parameters, either through implication (&'x+y') or with the arrow ('x y -> x*y'). I haven’t thought of a case where that would be a win over using a Ruby block: { |x, y| x*y }.

I’m divided about the underscore notation. It seems like a good compromise for expressions where there is a single parameter and it doesn’t fall on the left or the right side of an expression. Standardizing on an unusual variable name is, I think, a win. Underscore often means a “hole” in an expression or a computation, so it feels like a good fit. I would honestly much rather see something like: &'(1/_)+1' than &'(1/x)+1'. The underscore jumps out in an obvious way, and it wouldn’t be magically clearer to write { |x| (1/x)+1 }.

That being said, I haven’t actually written an underscore expression yet in actual code, so far I’m getting by using the point-free expressions to simplify things and using Ruby blocks for everything else.

RSpec

describe "String to Proc" do

before(:all) do
@one2five = 1..5
end

it "should handle simple arrow notation" do
@one2five.map(&'x -> x + 1').should eql(@one2five.map { |x| x + 1 })
@one2five.map(&'x -> x*x').should eql(@one2five.map { |x| x*x })
@one2five.inject(&'x y -> x*y').should eql(@one2five.inject { |x,y| x*y })
'x y -> x**y'.to_proc()[2,3].should eql(lambda { |x,y| x**y }[2,3])
'y x -> x**y'.to_proc()[2,3].should eql(lambda { |y,x| x**y }[2,3])
end

it "should handle chained arrows" do
'x -> y -> x**y'.to_proc()[2][3].should eql(lambda { |x| lambda { |y| x**y } }[2][3])
'x -> y z -> y**(z-x)'.to_proc()[1][2,3].should eql(lambda { |x| lambda { |y,z| y**(z-x) } }[1][2,3])
end

it "should handle the default parameter" do
@one2five.map(&'2**_/2').should eql(@one2five.map { |x| 2**x/2 })
@one2five.select(&'_%2==0').should eql(@one2five.select { |x| x%2==0 })
end

it "should handle point-free notation" do
@one2five.inject(&'*').should eql(@one2five.inject { |mem, var| mem * var })
@one2five.select(&'>2').should eql(@one2five.select { |x| x>2 })
@one2five.select(&'2<').should eql(@one2five.select { |x| 2<x })
@one2five.map(&'2*').should eql(@one2five.map { |x| 2*x })
(-3..3).map(&'.abs').should eql((-3..3).map { |x| x.abs })
end

it "should handle implied parameters as best it can" do
@one2five.inject(&'x*y').should eql(@one2five.inject(&'*'))
'x**y'.to_proc()[2,3].should eql(8)
'y**x'.to_proc()[2,3].should eql(8)
end

end
Go ahead, download the source code for yourself.

Update: Reg smacks himself in the head!

I had a look at the source code for Symbol#to_proc:

class Symbol
# Turns the symbol into a simple proc, which is especially useful for enumerations. Examples:
#
# # The same as people.collect { |p| p.name }
# people.collect(&:name)
#
# # The same as people.select { |p| p.manager? }.collect { |p| p.salary }
# people.select(&:manager?).collect(&:salary)
def to_proc
Proc.new { |*args| args.shift.__send__(self, *args) }
end
end
Look at that: Although the examples are all of unary messages like .name, the lambdas created handle methods with arguments. And since almost everything in Ruby is a method, including operators like +… You can use Symbol#to_proc to do some of the point-free stuff I like:

[1, 2, 3, 4, 5].inject(&:+)
→ 15
[{ :foo => 1 }, { :bar => 2 }, { :blitz => 3 }].inject &:merge
→ {:foo=>1, :bar=>2, :blitz=>3}

Labels: , ,

 

Friday, October 26, 2007
  map(&"(1.._).inject(&'*')")
Some working Ruby code:

(1..3).map(&'*2') => [2, 4, 6]
(1..3).map(&'[-1, _, 0]') => [[-1, 1, 0], [-1, 2, 0], [-1, 3, 0]]
(1..3).map(&'x -> y -> x * y').map(&'[2]') => [2, 4, 6]
(1..5).select(&'>2') => [3, 4, 5]
(1..3).map(&'x -> y -> x * y').map(&'.call(2)') => [2, 4, 6]
[5].map(&"(1.._).inject(&'*')") => [120]


See String#_to_proc.

Labels: ,

 

Thursday, October 25, 2007
  Too much of a good thing: not all functions should be object methods
OOP is several different ideas put together, the most important of which is Fine-Grained Information Hiding.

One can think of information hiding as being the principle and encapsulation being the technique. A software module hides information by encapsulating the information into a module or other construct which presents an interface.
Information Hiding on Wikipedia


The basic principle of all OO languages is that relatively small things—such as individual accounts in a business program—each encapsulate both their data (in the form of members) and their algorithms (in the form of methods). Our notions of members and polymorphism both work to this goal of hiding information. There’s a lot more to most OO languages, such as whether they include a notion of types and what mechanisms they use for sharing common behaviour. But let’s look at this one principle: objects are responsible for their data and for their algorithms.

should objects be responsible for all of their own behaviour?

There’s a general idea that in a well-constructed program, each object “knows” how it ought to behave. That’s what its methods are for. Quite obviously, objects cannot be responsible for everything involving them in a program. If each object completely encapsulated all of the things it could do or be involved in, you would never pass one object as a parameter in a message to another object.

For every complex problem, there is a solution that is simple, neat, and wrong.
—H. L. Mencken


For example, you would never have collections. If every object “knew” how to organize itself into collections, you wouldn’t need an Array or Hash, would you? In practice, each object in a system can be involved in many different actions. It has to be responsible for some of them, and it has to play a secondary, passive role in others. Most OO programs do not have every object implement its own collections methods. They may include some form of specialization so you can have an array of accounts, but an array of accounts is still not an account.

subject.verb(object)

In the English language, we have the idea of a Subject and an Object in a sentence. For example, when we say “Jack loves Jill,” Jack is a subject and Jill is an object. Jack loves. Jill is loved. It’s the same in OO programs. Sometimes objects are actively doing things through their methods. Sometimes other object’s methods are doing things with them.

Verbing Weirds Language
—Bill Watterson, Calvin and Hobbes


Good OO design is, in part, doing a good job of choosing the right bifurcations: given a list of nouns and verbs, making the right decisions about which nouns ought to be the active nouns, the subjects, the ones that “own” the verb in the form of a method. And thus consciously making decisions about which objects ought to be the passive nouns, the objects of the verbs, the ones that don’t implement the methods.

Unfortunately, there are lots of places where we can err on the side of giving too much responsibility to individual objects. It’s understandable, given that OO is theoretically all about objects being responsible for themselves. But as in many other things, in practice good OO is about objects being responsible for a little as possible (but no less!), not as much as possible.

the kingdom of nouns

One common symptom of this problem is a system that has objects for all of the obvious nouns or entities, but not for the verbs. OO began with languages like Simula, where the paradigm was trying to represent real-world entities such as automobiles on a highway. From that time forward, the emphasis has been on having objects for each noun in the problem domain. In such traditionally-organized OO programs, the “verbs” or actions are all attached to objects as methods.




Object Design: Roles, Responsibilities, and Collaborations focuses on the practice of designing objects as integral members of a community where each object has specific roles and responsibilities. The authors present the latest practices and techniques of Responsibility-Driven Design and show how you can apply them as you develop modern object-based applications.


Not all “verbs” have a clear separation between a single entity that is the subject or active entity that ought to own the verb’s definition and the secondary, passive subject entities that should not own the verb’s definition. The easiest examples of this are operations that are intended to be commutative.

For example, many languages define addition as a method belonging to numbers or magnitudes. In Smalltalk, the expression 1 + 2 actually means “send the message + 2 to the object 1.” At first glance, this seems elegant: the number 1 handles the message + 2 as integer addition, while 1.0 would handle the same message with floating point arithmetic. What more could you want?

Well, there is a huge problem with this arrangement: Addition is commutative. 1.0 + 2 must give the same result as 2 + 1.0. Using a simple message to implement addition means that you must be excruciatingly careful to handle all of the possible cases so that you do not accidentally violate this property. Now of course, the designers of system classes like Integer and Float went to this trouble. But if you want to add another magnitude class—say CurrencytwoPlaceDecimal—you have to open up all of the system classes and modify them so that 1 + ThirtyCents gives the same result as ThirtyCents + 1.

beware of breaking symmetry

Of course, you may not need to implement a new magnitude class. Fine. But what about symmetric relations like comparison? This is a major pitfall for OO developers: in many cases you need to write a test of equivalence or equality (operations like ==, equal?, eql?, eqv? and all of the other variations on the same theme). In every one of these cases, horrible things will happen if your operation is not symmetric. For every case, x.eql?(y) if-and-only-if y.eql?(x).

This is obviously easy when x and y are both the same kind of object. What happens when they’re different, but still logically equivalent? It turns out that implementing commutative operations and symmetric relations as methods doesn’t work very well. It forces you to smear duplicate logic over many different classes (or prototypes, if your language swings that way).

Here’s a practical example. Let’s say you want to implement a form of equivalence for collections. For ordered collections like lists, what you want is that if two ordered collections have the same members, in the same order, they are equivalent. It’s easy to imagine writing such a method as a mixin for all of your ordered collections. It obviously knows about iterating over ordered collections (recursively, if you grew up with Godel, Escher, Bach on your night stand). Note that you may not have an indexed collection: you might have a list where you simply retrieve values in order.

And likewise, you can write a collection equivalence method for dictionaries like hash tables: if two objects have the same values at the same keys, they are equivalent. Again, a simple mixin will handle things for dictionaries.

Now comes the wrinkle: you decide that an ordered collection ought to be equivalent to a dictionary where the keys are the integers ascending from zero. In other words, ('foo' 'bar' 'blitz') ought to be equivalent to { 0 => 'foo', 1 => 'bar', 2 => 'blitz' }. How are you going to code this? Well, the dictionary mixin could obviously handle equivalence to an ordered list. But we need symmetry, so we have to “open up” the ordered collection mixin and add code for equivalence to dictionaries.

Actually I made up the term object-oriented and I can tell you I did not have C++ in mind. The important thing here is that I have many of the same feelings about Smalltalk.
—Alan Kay


I’m holding my nose, we have not one but two different code smells: 1) Why is one piece of logic in two different places? 2) Why do ordered collections know anything at all about dictionaries, and why do dictionaries know anything at all about ordered collections? The latter is especially disturbing: the whole point of OO is information hiding. How does having ordered collections and dictionaries knowing about each other help us to hide information?

The obvious answer to me is that the knowledge of how to compare an ordered collection to a dictionary does not belong in ordered collections or in dictionaries. The requirement that relations like equivalence be symmetrical across heterogeneous types implies that the types themselves cannot be responsible for implementing equivalence for themselves.

There are similar problems of code duplication and information leakage apply to modelling relations (why do we declare has_one and belongs_to in Rails) and implementing the <=> operator in Ruby. It looks like having verbs “belong to” the subject noun is often a good idea, but not always a good idea.

commuting the sentence of execution

Maybe some verbs belong to objects, but some are best on their own? Maybe + and <=> and equivalent? really ought to be emancipated from their subservience to objects and ought to have their own definitions.

There are two real approaches to object-orientation. The first is known as message-passing. You send an object a message and ask it to deal with it. (This would not work with many people in this newsgroup.) The meaning of the message is local to the object, which inherits it from the class of which it is an instance, which may inherit it from superclasses of that class…

The second approach is generic functions. A generic function has one definition of its semantics, its argument list, and is only specialized on particular types of arguments.
Erik Naggum discussing CLOS on comp.lang.lisp


What we ought to do is take some of the verbs and give them their own place in our programs, instead of hanging them off nouns. This isn’t such a revolutionary idea: Common Lisp’s Metaobject Protocol does this exact thing, providing generic functions. A generic function is, in effect, a verb raised to the same level of abstraction as a noun.

This isn’t some revolutionary idea limited to “powerful” languages either: the Java collections framework uses a Comparable interface for ordering collections. The compareTo(...) method belongs to an object. By way of—ahem—comparison, the Comparator interface extracts comparison out of the subject object and puts it in a separate function object. You can perform sorts in Java either way.

If we aren’t using Common Lisp, can we build the verbs we want out of the tools at our disposal? In other words, can we Greenspun generic functions in languages like Java and Ruby?

generic functions in java, plus a detailed look at method dispatching

Let’s start by thinking about generic functions in a Java-like language.

Returning to our example of writing equivalent?, we might make an Equivalent class with a single method, perhaps we can call it eval. So we end up with something like Eqivalent.eval(foo, bar). Java-like languages allow us to write different versions of the eval method with different type signatures, so we can write:

public static boolean eval (List foo, List bar) { ... }
public static boolean eval (List foo, Map bar) { ... }
public static boolean eval (Map foo, List bar) { return eval(bar, foo); }
public static boolean eval (Map foo, Map bar) { ... }

And so forth. Are we done?

No, our code is broken. What happens when we decide that the “default” equivalence is the == relationship. We can’t write:

public static boolean eval (Object foo, Object bar) { return foo == bar; }

This is hideously broken in languages like Java. You’re almost all nodding in agreement, but please be patient while I explain it anyway: you probably want to pass this along to someone who really needs to be told why it is broken, so why don’t I go ahead and explain it for them?

What you want is that if two objects are of the more specific types—List and Map—we will call the more specific version of the eval methods. But if we can’t “match” one of the more specific eval methods, we want to use eval (Object foo, Object bar). Too bad, that’s not how Java works. Java uses two completely different ways to figure out which method to call when you overload methods!

Way number one is is for figuring out that when you call noun.verb(...), where do we find the definition for verb? This lookup is effectively done at run time, so that even if your code looks like this:

public static void printSomething(Object foo) {
System.out.println(foo.toString());
}

Java will look up the method toString based on foo’s actual type when the method is called, even though you declared it to be an Object. That’s polymorphism at work, and it’s the information hiding working for us. Each object can do it’s own thing where toString is concerned, and we don’t have to worry about it. This is called single dispatch, because it figures out which method to call based on just one of the nouns, the subject noun a/k/a the receiver of the method invocation.

But that’s not what happens when we write this:

public static void printSomethingElse (Object foo, Object bar) {
if (Equivalent.eval(foo, bar))
System.out.println("2 x " + foo);
else System.out.println(foo.toString() + ", " + bar.toString());
}

It will always call eval (Object foo, Object bar). It will not call eval (List foo, List bar) if you pass it two lists. That’s because although each of our methods have the same name—eval—Java treats them as different methods, and it figures out which one to call based on the declared types of the parameters at compile time, not on the actual types of the parameters’ values at run time.




Free your mind with A Little Java, a Few Patterns: The authors of The Little Schemer and The Little MLer bring deep and important insights to the Java language. Every serious Java programmer should own a copy.



Besides writing a Lisp interpreter in Java, your next best bet for building a generic function the way we want it is to find a way to turn Java’s single dispatch into a multi-dispatch, to dispatch on two nouns, foo and bar.

The good news is this: dispatching at run time on two different types is a well-known problem, and the solution is called double dispatch. The problem with double dispatch is that it moves our equivalence code back into our nouns, and we don’t want that.

The Visitor pattern might be handy: it’s a way to add methods to an object at run time in a language like Java that supposedly doesn’t do that. If we decide that everything to be compared using Equivalent.evalimplements an interface called Visitable, we can build a double dispatch system that doesn’t require putting an equivalent? method in the entities being compared:

interface Visitable {
Object accept(final Visitor visitor);
}

interface Visitor {
Object visit(final Object obj);
Object visit(final List list);
Object visit(final Map map);
}

public class Equivalent {

static boolean list_list (List foo, List bar) { ... }
static boolean list_map (List foo, Map bar) { ... }
static boolean map_map (Map foo, Map bar) { ... }
static boolean object_object (Object foo, Object bar) { ... }

public static boolean eval (final Visitable foo, final Visitable bar) {
return foo.accept(
bar.accept(
new Visitor () {
public Object visit(final Object bar) {
return new Visitor () {
public Object visit(final Object foo) {
return object_object(foo, bar);
}
public Object visit(final List foo) {
return object_object(foo, bar);
}
public Object visit(final Map foo) {
return object_object(foo, bar);
}
}
}
public Object visit(final List bar) {
return new Visitor () {
public Object visit(final Object foo) {
return object_object(foo, bar);
}
public Object visit(final List foo) {
return list_list(foo, bar);
}
public Object visit(final Map foo) {
return list_map(bar, foo);
}
}
}
public Object visit(final Map bar) {
return new Visitor () {
public Object visit(final Object foo) {
return object_object(foo, bar);
}
public Object visit(final List foo) {
return list_map(foo, bar);
}
public Object visit(final Map foo) {
return map_map(foo, bar);
}
}
}
}
)
)
}
}

If that looks like a lot of work to you, I agree. You’re basically replicating Java’s run time dispatching on two types, so you need a bit of a matrix. Is it worth the effort? Let’s consider what this wins you:


And best of all, you have a nice place for your verbs, and they are no longer second-class citizens behind the nouns.


Update: A few people have suggested alternate approaches to implementing multiple dispatch in Java. I think there are various trade-offs to be made, and several different implementations ought to be considered before you write production code.

However, the point of the article is to suggest that not all functions should be implemented as methods of subject objects. I think it makes that point regardless of what you think of using a Visitor and a double dispatch.

Here’s an alternate approach from Laurie Cheers:
interface Classifiable
{
int classify();
}

// I know this isn't valid Java, but it makes the example much clearer. The alternative is to tiresomely spell out every combination.
#define PAIR(a,b) (a|(b<<4))

abstract class DoubleDispatchable
{
abstract Object list_list(List a, List b);
abstract Object list_map(List a, Map b);
abstract Object map_map(Map a, Map b);
abstract Object object_object(Object a, Object b);

const int OBJECT = 0;
const int LIST = 1;
const int MAP = 2;

Object dispatch(Classifiable a, Classifiable b)
{
switch(PAIR(a.classify(), b.classify))
{
case PAIR(LIST, MAP): return list_map(a,b);
case PAIR(MAP, LIST): return list_map(b,a);
case PAIR(LIST, LIST): return list_list(a,b);
case PAIR(MAP, MAP): return map_map(a,b);
default: return object_object(a,b);
}
}
}

class Equivalent extends DoubleDispatchable
{
Object list_list(List a, List b) {...}
Object list_map(List a, Map b) {...}
Object map_map(Map a, Map b) {...}
Object object_object(Object a, Object b) {...}

bool eval(Classifiable a, Classifiable b) { return dispatch(a,b) != false; }
}

What trade-offs, you ask? The Visitor pattern given gets the compiler to guarantee that you write each of the nine cases, whereas hand-written tests and logic simplifies the code.

I specifically chose the Visitor pattern because it seemed more in keeping with the spirit of the Java language and culture, trading verbosity for compiler safety.

I'm extremely comfortable with the other trade-off, emphasizing readability and simplicity. Although, if you go far enough down that road, you might as well look at other languages ;-)

Labels: , ,

 

Wednesday, October 24, 2007
  Google Map of the San Diego County Fires
Google Map of the San Diego County Fires.

This takes my breath away. Considering that a little less than a year ago I wrote this, I ought to be thinking about how online maps could change our lives every day. But yet... this amazes me.
 

  Off-topic: For raganwald RSS subscribers only
If someone calls you a horse, laugh. If someone else calls you a horse, think about it. If a third person calls you a horse, start shopping for a saddle.

I have now received my second request for an RSS feed that does not include a daily summary of links I find relevant to this weblog. So I’m thinking about dropping them outright.

I’m not thinking about offering three feeds (one just links, one just posts, and one blended). I’m not even thinking about offering two feeds. There is one feed for this weblog; the question I am asking myself is whether it should contain my words or whether it should contain my words and a daily summary of interesting links.

I’m interested in hearing your opinion: I have added a poll to the weblog’s pages, or you can vote right here:

I like the links, keep sending them.
No thanks, please only send posts and essays.
  
pollcode.com free polls
Thanks!

This is a DWTFYWT poll, meaning I am soliciting your opinion, not your edict :-)
 

Monday, October 22, 2007
  Mea Culpa
At one time I was just scraping by selling my own classified advertising software for desktop publishers. One user was XTRA, Canada’s largest newspaper for the Gay community.

Naturally, their database of customers and ads was sensitive. But I needed to take it home from time to time to debug things. So I wrote a “scramble” routine that shuffled names around, changed all the phone numbers to 555-xxxx, changed the credit card numbers randomly, and so forth. When I needed to take the database off-site, I would log out, duplicate the database, log back in, and run the scramble routine on the dup.

The menu item for this routine was called “Fruit Salad,” and it only appeared when I logged in. One day I was at their office debugging something, and their manager saw the menu item.

“What’s that?” He asked. I was embarrassed, it suddenly occurred to me that my little joke was inappropriate and insensitive. “Uh, nothing…” I stalled, and while I tried to make up a good explanation, he grabbed the mouse and selected it.

On the live database.
 

  The Shipping News
Joel Spolsky has announced that Evidence-Based Scheduling is shipping as part of FogBugz 6.0, available now. This is the sort of thing I had in mind when I started to wonder whether we can predict the future of a software development project with objective observation?

In fact, I built a prototype that did the exact thing that FogBugz is doing quite some time ago. However, prototypes are not shipping products. FogBugz is a shipping product. My prototype was not. And that makes all the difference.

One of the challenges I faced was that I was trying to solve the wrong ^H^H^H ^H^H^H^H^H a different problem. I was not trying to solve the “when will we ship” problem, I was trying to solve the green-shift problem. In other words, I was trying to solve the “when will we ship” problem given the basic assumption that people will attempt to game the program to deliver the green light.

I failed to solve that problem. Unfortunately, I did not fail in such a way that I succeeded in solving a simpler problem. Instead of turning working prototypes into money, I was casting them aside, muttering, “not enough.”

For example, I was (and still am) very interested in how project dynamics change over time. I have observed that some teams have a fairly steady velocity, while others trail off drastically as they near the alleged ship date. So I wasted a lot of time trying to find out how to classify projects based on the evidence they generate in the early stages of development. Meanwhile, of course, I could have and should have packaged something up and just shipped it.

All the thinking in the world has not helped anybody ship more software. But FogBugz 6.0 will, because it is shipping. Shipping matters.
 

  Gold-plating code is unsound, but armour-plating it is a good idea
Write all your code “clean,” the first time you write it. Make classes for everything. Use enumerated types. Don’t take shortcuts. Don’t have any part of the code where you say, “Oh, yah, I just glossed over that for now.” You are NOT going to go back and fix it. Seriously, how often do you say to yourself, “I think I’ll dive into this messy code today and try to make it nice and pretty without adding any functionality?” Nobody is going to pay you for that. In fact, I got called on the carpet for cleaning code during a major update to a piece of software at a previous job — “What are you doing spending time modifying code that already works? Just add your new features and be done.” Never mind that I couldn’t understand the code, or that clean code is stable, maintainable, extensible code.
—Wil Shipley, Free programming tips are worth every penny
 

Sunday, October 21, 2007
  How to use a blunt instrument to sharpen your saw
In sales, there is a very high, observable, and measurable correlation between attending sales training seminars and sales volume. One explanation for this is that the kind of people who take time off of selling to sharpen their own saw are the kind of people to be top salespeople.

The other possibility is that there is something abut the seminars themselves that make salespeople better. I have asked salespeople about it, and generally I get a variation on the exact same answer: If I can learn just one thing that improves my sales skills, the seminar will pay for itself.

Think about that. They go to an all day seminar, where they will probably hear twenty, thirty, or forty tips. They will probably sit through tip after tip thinking “Yawn, I knew that, tell me something new.” Or they hear something and think: “That is the worst suggestion I’ve ever heard.” But then, suddenly, they hear something new, and they profit from it.

In sales, you are used to making call after call, facing rejection after rejection, but you keep dialing because… the next one could be a winner. So the kind of person who can keep on dialing after rejection ought to be the kind of person who can sit through a seminar waiting to pounce on one new thing that can improve their income.

Is this how we learn about programming? No!

What we do is this: we read a blog post, reading thing after thing we agree with, and if just one thing in there doesn’t fit our personal world view, we demand a correction. If the thesis of the post clashes with our prejudices, we accuse the author of being an idiot. Honestly, we would suck as salespeople. We would quit the first time someone disagreed with us.

It’s a win for me if I get selfish and try to ignore the stuff I already know and the stuff I dislike and hunt for the one thing that makes me better.

What I suggest we do is mimic these salespeople. When we read a post, or a book, or look at a new language, let’s assume that some or even most of it will not be new. Let’s assume that we’ll positively detest some of it. But let’s also look at it in terms of our own profit: we win if we can find just one thing in there that makes us better programmers.

That’s all we need from a blog post, you know. It’s a huge win if there’s one thing in a post. Heck, it’s a huge win if we read one hundred posts and learn one new valuable thing.

This is what I’ve learned from sales: It’s a win for me if I get selfish and try to ignore the stuff I already know and the stuff I dislike and hunt for the one thing that makes me better.

When someone says something outrageous, like: Fuck compilers and their false sense of security, it is not important whether I happen to think that programming languages with strong, expressive type systems are valuable (hint: I do). What is important is to look at this statement and ask yourself: Is there just one thing in there, one kernel of wisdom that I can extract and use to be a better programmer?

I think there is a lot of useful stuff to be extracted from that one outrageous statement. So much so that it is not important to me whether, on the whole, compilers are a bad idea. And likewise, it is not important to me whether debuggers are always a bad idea.

No more important than asking a salesperson if, on the whole, she thought the seminar presenter was any good. She’ll be too busy using the one thing she learned to give any thought to the question.

Raymond Smullyan does much more than write about Infinity, Combinatory Logic, Recursion Theory, and Gödel’s Incompleteness Theorems. And he does much more than teach these concepts delightfully by turning them into stories and puzzles to solve. He also teaches philosophy by way of insightful essays and anecdotes.

I’m going to paraphrase one of his down-home insights. This particular little story has helped me through many dark periods in my life. Raymond was talking about Taoism, and he explained that his two pet dogs embrace the Tao. I think he described them as “Sages.”

Raymond explained that like many dogs, they preferred rich chunks of meat and gravy to dried kibble. And like many people, Raymond had tried making the kibble more palatable by mixing in some meat with the dry dog food and pouring gravy over the whole thing.

The dogs, of course, would carefully pick the meat out and lick up all the gravy, leaving nothing but the dried kibble behind. But did they resent this? Did they howl and whine about the kibble ruining the meat? Of course not! They would wag their tails and frisk about, joyous in finding all that good meat and tasty gravy in their bowls. It was like the kibble existed in some alternate dimension that the dogs could not perceive.

Aaah… Dogs truly are Sages.
Programmers are Sages


(Part I of “What I’ve Learned from Sales,” Don’t Feed the Trolls, looked at why resistance to a new idea is expressed as a never-ending series of objections. Part II, Wanna Bet?, described how to handle one very common form of objection.)


Update: A couple of thoughts after sleeping on this post.
 

Thursday, October 18, 2007
  Compare and contrast
Since Fortran doesn't have a structured IF, REPEAT ... UNTIL, or CASE statement, Real Programmers don’t have to worry about not using them. Besides, they can be simulated when necessary using assigned GOTOs… The determined Real Programmer can write Fortran programs in any language.
Real Programmers Don't Use Pascal


Any sufficiently complicated C or Fortran program contains an ad hoc, informally-specified, bug-ridden, slow implementation of half of Common Lisp.
Greenspun’s Tenth Rule
 

  The challenge of teaching yourself a programming language
Programming as a profession requires a great deal of learning on one’s own. Whether you think Universities should or should not be in the business of providing job training for software development, the fact is that the industry moves far too rapidly for Universities to teach more than a small portion of the knowledge required to be competent on the job, even at an entry level.

Teaching oneself involves more than just reading a book and playing around, sometimes it involves taking time to investigate the parts that don’t immediately make sense. (Note that those steps are the shortest, simplest path from confusion to understanding; it might take someone more work than that, but the fact remains that there is a simple and reasonable path to understanding and that it isn’t particularly hard to find.) If one does not know how to learn on one’s own, self-teaching is the wrong choice…
—Gregory, The Magic in the Box


You have to take responsibility for teaching yourself, and that is a far greater responsibility than skimming a book and fooling around copying and pasting code from web pages. You can’t just take basic or even sketchy knowledge of how to program in one language and “transfer” it to another language. You think you can just “pick it up,” but in reality you can’t, and neither can I. Even Peter Norvig needs ten years to learn a new language.




Essentials of Programming Languages introduces programming languages in one of the strongest ways possible: by building a simple interpreter for each language concept (The “P.J. Plauger” method). There are other important ways to learn a programming language, but none will teach you as much about how language features actually work.

Returning to the quote, there is a temptation to think of learning a new language or system in terms of your facility with problems you set for yourself. Meaning, you pick up a new language and immediately try to perform some task with it. A task you choose. And you probably have a preconceived idea of how to go about solving the task. And when you have successfully performed that task, you think you have learned the language.

When put this way, it is obviously nonsensical. It is like writing a test where you choose the questions.

But this type of thinking leads to skirting around or avoiding anything confusing or “difficult.” This type of thinking avoids anything truly new and different in favour of using the new language as closely as possible to how you use your existing languages. And that means that you really haven’t learned anything worthwhile, just some new syntax.

To truly learn a new language, you have to learn the different things. When you find something difficult, something that doesn’t make sense, you don’t avoid it, you embrace it. This is where the actual learning takes place. For example, it is possible—even easy—to write Ruby programs that do not use blocks. They work just like Java programs. But of course, such a program isn’t really a Ruby program in any substantial sense. If you were to avoid blocks because (a) they look weird, and (b) you can write your program without them, in what sense have you learned how to program in Ruby?




Types and Programming Languages will introduce you to programming languages in a fascinating way: by examining the different type systems behind them.

Imagine yourself as a master carpenter who is training an aspiring apprentice. The apprentice has assembled some Ikea furniture and decided he likes carpentry, so he’s going to give it a whirl. One day, he brings in a stool with a leg that needs replacing. He says, “I’ve been trying to remove the leg, but the screw is just stuck or something, and I think something is wrong with it.” You look, and ask him to show you how he’s tried to go about it. He picks up a screwdriver and desperately tries to fit its flat head into the cross of the phillips screw. You tell him to stop, take out a phillips screwdriver, and proceed to unscrew things easily. He gawks and asks, “There are different kinds of screws that need to be treated differently?”

Imagine your horror. How could he not know something so basic? Aspiring to be a carpenter requires understanding the tools a carpenter uses. Likewise, aspiring to be a programmer requires understanding the tools a programmer uses. [ibid]

When learning a new language or tool, do not shy away from things that seem different, weird, confusing, counter-intuitive, or unfamiliar. Do not put them off because you can work around them. Learn them, try them, and persist with them until you discover why they make sense. This is the true road to teaching yourself a new language. And in today’s fast-moving industry, it’s a road we all share.
 

Monday, October 15, 2007
  Until you understand how FORTH is written, you’ll have only a very superficial understanding of how to use it.
FORTH is one of those alien languages which most working programmers regard in the same way as Haskell, LISP, and so on. Something so strange that they’d rather any thoughts of it just go away so they can get on with writing this paying code. But that’s wrong and if you care at all about programming then you should at least understand all these languages, even if you will never use them.

LISP is the ultimate high-level language, and features from LISP are being added every decade to the more common languages. But FORTH is in some ways the ultimate in low level programming. Out of the box it lacks features like dynamic memory management and even strings. In fact, at its primitive level it lacks even basic concepts like IF-statements and loops.

Why then would you want to learn FORTH? There are several very good reasons. First and foremost, FORTH is minimal. You really can write a complete FORTH in, say, 2000 lines of code. I don’t just mean a FORTH program, I mean a complete FORTH operating system, environment and language. You could boot such a FORTH on a bare PC and it would come up with a prompt where you could start doing useful work. The FORTH you have here isn’t minimal and uses a Linux process as its ‘base PC’ (both for the purposes of making it a good tutorial). It’s possible to completely understand the system. Who can say they completely understand how Linux works, or gcc?

Secondly FORTH has a peculiar bootstrapping property. By that I mean that after writing a little bit of assembly to talk to the hardware and implement a few primitives, all the rest of the language and compiler is written in FORTH itself. Remember I said before that FORTH lacked IF-statements and loops? Well of course it doesn’t really because such a language would be useless, but my point was rather that IF-statements and loops are written in FORTH itself.

Now of course this is common in other languages as well, and in those languages we call them ‘libraries’. For example in C, ‘printf’ is a library function written in C. But in FORTH this goes way beyond mere libraries. Can you imagine writing C’s ‘if’ in C? And that brings me to my third reason: If you can write ‘if’ in FORTH, then why restrict yourself to the usual if/while/for/switch constructs? You want a construct that iterates over every other element in a list of numbers? You can add it to the language. What about an operator which pulls in variables directly from a configuration file and makes them available as FORTH variables? Or how about adding Makefile-like dependencies to the language? No problem in FORTH. How about modifying the FORTH compiler to allow complex inlining strategies — simple. This concept isn’t common in programming languages, but it has a name (in fact two names): “macros” (by which I mean LISP-style macros, not the lame C preprocessor) and “domain specific languages” (DSLs).

This tutorial isn’t about learning FORTH as the language. I’ll point you to some references you should read if you’re not familiar with using FORTH. This tutorial is about how to write FORTH. In fact, until you understand how FORTH is written, you’ll have only a very superficial understanding of how to use it.
—Richard M. Jones, A sometimes minimal FORTH compiler and tutorial
 

Friday, October 12, 2007
  Every word can have strength, meaning, and purpose when used appropriately
Some of you may think that you don’t need the “fucking” in “do it fucking now”. You do. You need that impact, that force, that call to action and mostly, that kick in the ass to get you moving. Otherwise, you’ll end up another loser that had a great idea a long time ago but never did anything about it. Dreamers don’t make money. Doers make money. And doers “Do it Fucking Now.”
Do It Fucking Now.


Q: Can’t you change the wording? It’s inappropriate / childish / not corporate-compliant.

A: What the fuck is not clear in “DO WHAT THE FUCK YOU WANT TO”? If you do not like the license terms, just relicense the work under another license.
WTFPL—Do What The Fuck You Want To Public License
 

  Updated subscription information for raganwald
Please adjust your feed-reader to consume http://feeds.raganwald.com/raganwald. If you aren't sure how to do that, simply add this weblog again and your reader will pick up the new settings.

Thank you.
 

Thursday, October 11, 2007
  Three stories about The Tao
That maverick framework author is self-centred and vain. His framework is all about solving his problems, his way, he refuses to look at what the market wants and build something that could be more popular.

There was once a monk who would carry a mirror where ever he went. A priest noticed this one day and thought to himself “This monk must be so preoccupied with the way he looks that he has to carry that mirror all the time. He should not worry about the way he looks on the outside, it’s what’s inside that counts.” So the priest went up to the monk and asked “Why do you always carry that mirror?” thinking for sure this would prove his guilt.

The monk pulled the mirror from his bag and pointed it at the priest. Then he said “I use it in times of trouble. I look into it and it shows me the source of my problems as well as the solution to my problems.”

Sure, the big corporate framework and its language have problems, but they pay the bills.

Once there was a horse tied up on the side of the street. Whenever someone tried to pass, the horse would kick them. Soon a crowd gathered around the horse until a wise man was seen coming close. The people said “This horse will surely kill anyone who tries to pass. What are we going to do?” The wise man looked at the horse, turned and walked down another street.

Those rabid evangelists turned me off with their attitude, so I determined then and there to never look into their stuff, ever.

A monk and his novice were walking through the forest. They come to a stream. On the bank there was a beautifully dressed woman, crying. The monks asked her what was the matter. “I am on my way to a wedding. I have to cross the stream to get there, but the bridge has been washed away. I was searching for a place to cross where I wouldn’t ruin the dress, but I can’t find one and if I don’t make it across soon, I will be late.”

Without a word, the elder monk scooped her into his arms, waded across the stream, and deposited her on the other side. Ignoring her thanks, he waded back and the two monks resume their walk. They continued on their journey, but the younger monk was agitated and obviously had something on his mind. The elder monk stopped and asked him what was the matter.

“Elder, I am confused. Our vows prohibit us from fleshly contact with women, yet you embraced that woman in your arms. How can this be?” The elder monk eyed his novice with kindly concern. “Novice,” he asked, “I left her on the bank of the stream. Why do you still carry her?

I've read or heard these stories (and quite a few more) many times and in many forms. I borrowed the wording for the first and second story from this good page. Also, someone was kind enough to point outthat these stories are not necessarily about the Tao, and how Taoism is different from Zen, and so forth. Just so you know :-)

Labels:

 

Wednesday, October 10, 2007
  Cronic complaint
Further evidence that the users are revolting:
personally, i think, that the height of computing was ‘cron’. you needed a report every morning, put it in cron. you needed to analyze data every week, put it in cron.

computing was supposed to automate. supposed to make everyones lives easier by helping the person. now look at it. walk into any corporate office and you’ll see countless people (myself included) clicking on this and that to satisfy what the computer wants out of you. it feels like you are there to help the computer achieve uptimes, or defragged disks, getting rid of viruses, blocking ports, unblocking ports…

am i there to help the computer do it’s job? or is the computer there to help me do mine?

Snarfed shamelessly from Hooya’s comment on Slashdot.
 

Tuesday, October 09, 2007
  I'm confused
After reflection, this feels like it doesn’t carry enough idea mass to deserve a blog essay, but it isn’t brief enough to qualify as a twitter-like micro-post.


I just stumbled across a parenthetical remark about Why are local variables bad?, an article wherein I started to talk about why it is important to really understand the objective of refactoring code, not just the mechanical process. I then got to the title’s point, that mutable local variables are bad, and why I feel that way.

Ocean wrote:
Local variables aren’t bad they’re just confusing. A lot of times people use the word ‘bad’ when they really mean ‘confusing.’

This is interesting. When we are talking about computer programs, I suggest that confusing code is always bad. Perhaps there are “degrees of bad,” and local variables are less bad than, say, dangling pointers. But overall, isn’t it bad to confuse?

I guess my personal mantra is that programs must be written for people to read, and only incidentally for machines to execute (and here’s the entire text online).

Code that is confusing is difficult to understand. I pointed out that mutable local variables make code difficult to refactor. But hark! The problem is not that it’s difficult to refactor: that’s a symptom. The problem is that the logic is entangled and tightly coupled, such that it is difficult to decompose it into smaller blocks, to move pieces around, or to share common code.

Now there’s a kind of confusion that comes from unfamiliarity. If you grew up with Haskell, perhaps mutation will make your hair stand on end when you first see a BASIC program in all of its glory. But honestly, I have used mutable state since 1974, and it is not getting any easier.

There’s something intrinsically confusing about mutable local variables, and I suggest that this—in and of itself—is bad to the bone.
 

Sunday, October 07, 2007
  A new way to use the web to compare programming languages
I won’t pretend this means anything too significant, but consider this possible experiment: You know how people do quasi-statistical studies by counting web pages with words in them? For example, counting how many blog posts mention the word “Ruby” and seeing if it’s going up or down?

So here’s my simple experiment. First, start with two programming languages. For example—you thought I was going to say Ruby and Java, didn’t you?—Python and Lisp.





How do the experts solve difficult problems in software development? In Beautiful Code, leading computer scientists offer case studies that reveal how they found unusual, carefully designed solutions to high-profile projects. You will be able to look over the shoulder of major coding and design experts to see problems through their eyes.

Using some sort of semantic search algorithm, or perhaps by employing thousands of people to search by hand, or even just relying on our infinitely reliable “gut instincts” to make an estimate, let’s find all of the What I learned from Python that makes me a better programmer when I use Lisp posts, (and of course all the What I Learned from Lisp… posts as well). If there are a lot more Python -> Lisp posts than Lisp -> Python posts, what does that tell us?

I think if a lot of people write that Python teaches them stuff that makes them better Lisp programmers, it tells us that in some sense, Python is greater than Lisp. It might be the language. It might be the culture. It might be the benevolent dictator. And if the reverse were to be true, that more people write about how learning Lisp makes them better Python programmers… Doesn’t that tell us something about why Lisp is greater than Python in some deep sense?

I think this hypothetical experiment would tell us something about the value of a language for making you a better programmer. I consider that a very important characteristic of a programming language. Popularity comes and goes. Jobs using a particular language come and go. But being a better programmer is forever.

Okay, I know you’re dying to apply this to whatever language flame war is raging at the moment. Fine. The very next time someone complains that language X sucks compared to Language Y… Fire up your blog search engine and see which language has the most to teach you about being a better programmer.
 

Friday, October 05, 2007
  D is for "D'oh! We should have gone with P!"
I’m too busy right now to do an essay, but I need to say something about Theory D, Theory P, and economic interests. Several people have pointed out that Theory D is more attractive to “stake holders” than Theory P. Here are my unvarnished thoughts:

So there are two issues: what people believe about how projects work, and what deals people negotiate with each other. I believe that the adversarial negotiation games do contribute to fixed schedules, I agree with that. But I think it’s often evidence of stake holders who have embraced Theory P, not the opposite.

Now, if a development team agree to a fixed schedule, make a plan, and then toil according to the plan without acknowledging change, without updating the plan as they go... That’s Theory D in a nutshell.

Now I have to get back to work. Are we good on this? Thanks for listening to me vent.
 

Wednesday, October 03, 2007
  Three blog posts I'd love to read (and one that I wouldn't)
“Blogging about blogging” is tiresome, and I apologize in advance for inflicting this on you: I promise to return to technical subjects immediately. But I really do want to read what you have to say, and what better way than to full-on ask you to write?

So here are three blog posts I’d love to read. Write any or all of these, and you have a guaranteed bookmark in my delicious feed and my vote on sites like programming.reddit.com and dzone.com.

What I learned from Language X that makes me a better programmer when I use Language Y

Everybody has a pet language. And many smart people take a crack at learning a new language. Some take two years to try to port an existing, production application. Some read a book and throw it across the room, unconvinced that the new language offers much in the way of value. Whether you immersed yourself in the new language or merely skimmed it, what did it teach you that you can apply to your everyday work?

I disqualify things like “Programming in Assembler reminded me how much I love Object-Oriented Programming in Common Lisp.” Bzzzt! It has to be something you didn’t know before you tried Assembler. Here’s one of my own: Ruby and Javascript support a rich literal notation for collections that made me a better Java programmer: I learned the double-brace initialization idiom and now use it regularly (I liked it so much, I wrote an entire post about it.)

LISP is worth learning for a different reason—the profound enlightenment experience you will have when you finally get it.

The most amazing example of this kind of thinking is Eric Raymond’s famous quote: “LISP is worth learning for a different reason—the profound enlightenment experience you will have when you finally get it. That experience will make you a better programmer for the rest of your days, even if you never actually use LISP itself a lot.”

You may not experience a profound enlightenment from your next language. But if your mind is open to the possibilities, I bet you’ll learn a lot that will make you a better programmer for the rest of your days. Tell us about it.

Something surprising that you probably wouldn’t guess about Language X from reading blog posts

I get that Java is verbose, that static typing finds bugs and makes it easy to add certain features to IDEs, that there are a lot of jobs writing Java programs, and that there are a lot of frameworks and libraries written in Java. Great. But one more post about those subjects had better be really, really insightful if it is going to get me excited.




The Little MLer introduces ML (and its object-oriented variant Ocaml) through a series of entertaining and straightforward exercises working with lists, structures, and even deriving arithmetic from types.

Learning ML through the book’s ten brief chapters will stretch your understanding of how to leverage types and type checking to write programs that are more than just type-safe but are also semantically correct.

The surprising thing I learned from ML is the power of expressing a program’s semantics with types. It has made me a better programmer whether I’m using a weakly but statically typed language like Java or a dynamically typed language like Ruby.

What can you tell me that might not be obvious from reading the same-old, same-old blog posts out there? For example: Java’s Annotations provide a unique meta-programming mechanism that allows you to write programs that are familiar to the everyday programmer but add code-generation magic.

If I were coming to Java from the Ruby world, this might get me excited enough to really learn how to make my programs sing. I was excited to discover that the IntelliJ people have developed @Nullable and @NotNull annotations that add null-checking to Java at compile time.

The canonical example of this type of post is probably Douglas Crockford’s essay describing how Javascript is The World’s Most Misunderstood Programming Language.

My personal transformation about Idea X

Bob Sutton wrote an amazing article about one kind of smartness, Strong Opinions, Weakly Held. Now it’s great if learning a language or trying a new methodology taught you something new.

But it’s really, really fascinating if you happened to change your mind about something you used to think was critical. If you have had a 180 degree change of heart and embraced what you formerly shunned, or now shun what you formerly embraced.

And I don’t just mean write and tell me the logical reasons that Ocaml taught you how strong typing can be much more powerful than what lame-ass Language X provides. That’s true. But please, if that’s all you want to write, write “Five new things I learned from Ocaml that made me a better programmer when I use Lame-Ass language X” or “Something surprising that you probably wouldn’t guess about Ocaml from reading blog posts.”

This blog post is about YOU. Tell me about your personal journey. Give me the human story. When was it exactly that you had your Aha! moment? How did it feel to let go of years of prejudices and preconceptions? What did it feel like to take the red pill?

Now that Ruby on Rails is having its fifteen minutes of fame, people are lining up on either side of the love/hate divide and everybody seems to take its pluses and minuses for granted. But do you remember how dramatic it was when people like Bruce Tate had their “Born Again” moments? Maybe today their enthusiasm seems subjective and “unprofessional.” But there’s a human story there: when people turn their back on two, five, or even ten years of belief in something, there is a powerful story to be told.

And honestly, I want to hear your story, if you would care to tell it.

I would read any and all of the above three posts with enthusiasm and a deep respect for you stepping outside of the usual same-old, same-old blog posts about languages and tools. But if you choose to write the next kind of post, it’s going to be hard for me to get excited:

Here’s why such-and-such fhpxf tbng qvpx

I am not criticizing anyone who has strong opinions about why certain things are lame.




The Seasoned Schemer is devoted to first class functions (“closures,” as they are known to many). This book is approachable and a delight to read, but the ideas are provocative and when you close the back cover you will have learned how to compose functions out of other functions, whether you code in Java, Ruby, Javascript or just about anything else.

Just because it’s hard to prove something is lame doesn’t mean we should wander around saying that everything has its place and they’re all equally valuable and they all deserve the same real-estate in our minds.

We have to wield the axe and say NO to things, to decide that life is too short for programming in Language Z, or for struggling with Tool Omega, or for hiring people who don’t have a certain kind of degree, or whatever else you know in your heart to be lame.

But speaking as your reader, posts telling me why you’re saying “no” aren’t that helpful. They tell me a lot… about YOU and your preconceptions, not about the lame things. When I re-read my own posts about failure or about metaphors for software development, I now think they say more about me and my journey than they do about shipping software.

The most useful purpose posts about “how lame things are” serve is to help people rationalize decisions they have already made.

If I have already decided that Ruby is flawed, your post giving your seven reasons is useful ammunition when somebody asks me to justify writing Project Foo using server-side Javascript. But am I really sitting on the fence, unsure of what to do until I read your detailed critique? No.

The post that is going to push me away from the lame thing isn’t the post about how lame it is. It’s the post about the useful idea and how good it is. And that’s why I am asking—or even begging—you to write a post describing “Five new things I learned from Methodology P that makes me a better team leader when I use Methodology D,” or “Something surprising that you probably wouldn’t guess about the Factor language from reading blog posts,” or especially “My personal transformation about estimating software schedules.”

Thanks in advance.

Labels:

 

Reg Braithwaite


Nota Bene
A Brief History of Dangerous Ideas

Share
rewrite.rubyforge.org / ick.rubyforge.org / andand.rubyforge.org /