lets( :person => Person.find(:first, ...), :place => City.select { ... }, :thing => %w(ever loving blue eyed) ) { "#{person.name} lives in #{place} where he is known as the '#{thing.join(' ')} thing.'" }
Quite simply, #lets provides you with a way of making block-local variables. Ick already includes #let, which does almost exactly the same thing. However, #let is limited to just one variable:
let(Person.find(:first, ...)) { |person| ... }
Expanding #let to multiple variables with its existing syntax just doesn’t scale properly:
let( Person.find(:first, ...), City.select { ... }, %w(ever loving blue eyed) ) { |person, place, thing| "#{person.name} lives in #{place} where he is known as the '#{thing.join(' ')} thing.'" }
Thus, the #lets syntax uses a hash so that the variable names are close to the expressions denoting their values.
That’s all. If you are interested in why anyone would need #lets, read on…
Scope Creep
Recently there has been a lot of interest in exploring the extremes of OO style. One of the tenets of such a style is to work with small classes and short methods. Why do you suppose we want to do that?
Well, the underlying principle is to chunk things into small, workable pieces with clear purposes. This principle abounds everywhere: posts just like this are broken up into sections with headings and the prose is subdivided into paragraphs. So I quite agree with the principle behind small classes and short methods.
__________. You just knew that a word like “However” would follow a paragraph like that, didn’t you?
The principle of subdivision is terrific. But are classes and methods the only mechanisms we have for subdividing code? In some languages, that may be true. In other languages, that is not true.
For example, since version 1.1 Java has permitted classes to be nested inside of other classes, calling them “inner classes.” This is a very powerful technique of organizing code: If class A is the only class that ever uses class B, why should class B live in its own file, visible to every other class? Placing class B inside of class A is a big win: it is immediately clear that A is the only user of B, and when looking at the code in your IDE you do not see class B promoted to equal standing with A: it is clearly subordinate to A.
Of course, placing class B inside of class A makes A a bigger class. Is that wrong? Perhaps it is at some times, but it’s a big win at others. Remember we said B is subordinate to A? An inner class can be made private, explicitly telling the compiler and other programmers that it is limited in scope.
Limiting scope is a very powerful organizing technique in code. We can debate how important it is that the compiler enforce scope, however given the importance of writing code for humans to read and understand, I’m personally in favour of any technique that sends a strong signal to your fellow programmers explaining the intended structure and organization of the code.
Small Methods
There are techniques for organizing methods into classes or modules, and techniques for organizing classes and modules into larger classes and modules. But what about individual lines of code? Are methods really the only mechanism we have for organization at the lowest level?
I think not. Even within methods, there are certain practices that logically chunk your code into small, workable pieces with clear purposes. For example, Algol, Pascal, Modula, and many other languages support nested functions or procedures:
procedure print(var j: integer);
function next(k: integer): integer; begin next := k + 1 end;
begin writeln('The total is: ', j); j := next(j) end;
It is clear that #next is used solely by #print. Since most OO languages do not permit nested procedures, the programmer is left to choose between making #nest a private method or carving #print out and making it a strategy class. Making #next a private method does keep it from prying eyes outside of the class, however it implies that all methods of the class may want to use it, which is clearly not the case.
If we are allowed to nest objects, we can fake nested procedures with objects. Ruby’s Proc class makes it easy:
def print(j) next = proc { |k| k + 1 } p "the total is: #{j}" j = next.call(j) end
(There is a fairly major difference in what these two snippets of code do thanks to the difference between call-by-value and call-by-reference, but let’s wave our hands furiously and stick to the point about nesting functions.)
Containing Variables
In imperative languages, one of our biggest headaches is managing mutable local variables. If you only need one in one particular place, it is helpful to have a way of nesting the variable definition. In Java:
{ my $person = Person->find( first => ... ); my $place = City->select( sub { ... } ); my $thing = [qw( ever loving blue eyed )];
return $person->name() . " lives in $place where he is known as the " . join( ' ', @$thing ) . ' thing.'; }
The variables i and j are limited in scope to the body of the for loop. This called block scoping, and I personally love it. Block scoping permits us to make small, self-contained blocks of code and use them inline. If we need to move them or change them, we know which things are limited in scope to the block and which reach outside of the block and thus might be affected by our changes.
In Javascript we can fake block scoping using procedures, but it’s syntactically noisy. Can we do the same thing in Ruby? Yes, and that’s exactly what #lets does:
lets( :person => Person.find(:first, ...), :place => City.select { ... }, :thing => %w(ever loving blue eyed) ) { "#{person.name} lives in #{place} where he is known as the '#{thing.join(' ')} thing.'" }
This is a block with three block-local variables in it, just like you might find in Java. It breaks a complicated expression up into smaller pieces (“How to find the person,” “How to find the place,” “What kind of thing we have,” and finally “How to describe it all as a string”). And those pieces are all grouped together so you know they are not used elsewhere.
A Hack, wrapped in a Workaround, inside a Kludge
Unlike the other elements of Ick, #lets actually rewrites your ruby code. The code example above is actually rewritten as:
proc { |__121217088531733__| lambda do |person, place, thing| "#{person.name} lives in #{place} where he is known as the '#{thing.join(" ")} thing.'" end.call( __121217088531733__[:person], __121217088531733__[:place], __121217088531733__[:thing] ) }.call( :person => Person.find(:first, ...), :place => City.select { ... }, :thing => %w(ever loving blue eyed) )
The rewritten code is then evaluated. At the moment, this happens every time you call #lets, so it is expensive. Even by Ruby standards. Hopefully, there will be a future version of Ick::Syntax that only rewrites by need or perhaps just once when the code is first read.
So, #lets takes the syntactic noise of using procs to create block structure and hides it from us. How?
Well, my first cut at it used Ruby2Ruby and regular expressions. Then I was inspired by Aanand Prasad’s Haskell-style monad do-notation for Ruby to work directly with s-expressions. Although the code is technically longer, it’s actually much, much better. For meta-syntactic programming, you need to work with the abstract syntax tree.
And with ParseTree and Ruby2Ruby, you have all the tools you need to write code that writes code, with the teeny-weeny proviso that what you want to do is translate your Ruby into Lisp, manipulate the Lisp, and then translate it back into Ruby:
def rewrite_sexp(names_to_values, sexp) mono_parameter = :"__#{Time.now.to_i}#{rand(100000)}__" # the next four assignments are exactly why we want #lets: sorted_symbols = (names_to_values || {}).keys.map(&:to_s).sort.map(&:to_sym) parameters = if sorted_symbols.size == 1 s(:dasgn_curr, sorted_symbols.first) else s(:masgn, s(:array, *sorted_symbols.map { |sym| s(:dasgn_curr, sym) }) ) end values = s(:array, *sorted_symbols.map { |sym| s(:call, s(:dvar, mono_parameter), :[], s(:array, s(:lit, sym))) } ) body = sexp.last
s(:defn, :__anonymous__, s(:bmethod, s(:dasgn_curr, mono_parameter), s(:call, s(:iter, s(:fcall, :lambda), parameters, body ), :call, values ) ) ) end
Spam is the only truly limitless resource on the web and the ability to resist the endless waves of spam may well well be the single most important requirement of future distributed computing architectures…
Anybody who proposes a web architecture that doesn’t provide a means to handle spam is just engaging in wishful thinking.
Are you the customer?
I referred to Apple’s current business strategy with iPods as “delighting the customer.” Not everyone agrees that their industrial design, user experience, and iTunes business model is delightful for them, but I think everyone knows I meant they are trying to make money by making people happy with their purchases.
Likewise, news that Microsoft May Build a Copyright Cop Into Every Zune (followed by the denial-that-actually-doesn’t-deny-it “We have no plans or commitments to implement any new type of content filtering in the Zune devices as part of our content distribution deal with NBC.”). This does not mean Microsoft is not delighting its customers. Just the opposite.
And when I pass on a link to news that Microsoft Demos Zune Advertising Service, I am not saying they are not trying to delight their customers by finding a way to put Doritos’ logo feces on Zunes and XBOX 360s and other media they control. I am saying they are delighting their customers.
The key point is this: You are not Microsoft’s customer. You are not the person they want to delight. They want to delight big companies with big budgets. People who make money selling you music and selling you television and selling you snack foods.
It’s odd (to me) how deeply American culture has ingrained in its subjects the notion that they are first and foremost consumers.
For me, the cognitive dissonance first surfaced when I thought about television: The TV networks are the producers, the advertisers are the consumers, and the viewers are the product. TV is not primarily a means of delivering entertainment to viewers—it is a means of delivering viewers to advertisers.
It seems natural to think of ourselves as the end, but sometimes we're just the means…
Not that there’s anything wrong with delighting such people, the last time I checked I think that roughly 100% of my professional revenues have come from delighting companies. And thus I have only delighted people like you and I indirectly.
Remember when Microsoft paid a fee to EMI for every Zune sold? We know they must have built that fee into their pricing structure, passing those costs onto Zune owners, essentially charging them for music they planned to steal before they even took the Zune out of the box. But maybe that’s all for the benefit of Zune owners. What’s wrong with that?
And perhaps you benefit if Microsoft delights a music label such that you can subscribe to songs that evaporate when you stop paying a monthly fee. I certainly think you benefit from having a choice in the matter. And if looking at a bag of chips lets you listen to a song for a few days before deciding whether to buy said song, what’s wrong with that?
Absolutely nothing.
In truth, it does not matter whether Apple is trying to make money by forcing the music industry to offer all tracks for one low price, or whether Microsoft is trying to make money by delighting the kind of people who think that the same track ought to cost more if you download it over 3G than over WiFi. If a byproduct of these actions is a product or service that suits you, it’s all good. Be my guest and do business with whomever makes what you want to buy, regardless of their motivation or strategy.
And don’t let anyone tell you I said Microsoft doesn’t know how to delight their customers. I’m personally impressed by what they are prepared to do to make a buck.
p.s. I’d like to think I’m trying to delight you with my shameless use of Amazon affiliate links. Maybe I am, maybe I just like getting a few books and CDs every once in a while. Either way, have you heard Murray Perahia’s recording of Bach’s Goldberg Variations? While I still love both of Glenn Gould’s interpretations, I agree with a reader who wrote to say that “Perahia redefines this opus in a way I’d never have deemed possible.” It literally sounds like like a new work in Perahia’s hands.
p.p.s. I wrote this, then went back to work. Then I thought about it, and realized how remarkably small this post is, the obvious product of small thinking. Eleanor Roosevelt once said, “Great minds discuss ideas; Average minds discuss events; Small minds discuss people.” I am leaving the post up as a reminder to myself to of the consequences of giving in to small thinking.
¶ 2:02 PM4 comments
Are you doing anything next Tuesday, May 20th?
I’ll be speaking at meshU in Toronto, “A one-day event of 12 focused workshops in three streams (design, development, management) given by those who have earned their stripes in the startup game; people who can talk knowledgeably about everything from interface design to using Amazon’s S3 distributed server network.”
I’ll be talking about building and managing great teams. Actually, I’ll be facilitating an interactive discussion about building and managing great teams. I hope to use my experience working with Mobile Commons, Conversagent, KL Group, and others to guide a group investigation into what really works for hiring great people and managing for great results. (Note my obvious bias in suggesting the two are related).
My specialty is evidence-based project management, so when facilitating this discussion I’ll be trying to ferret out what actually works for people rather than what we emotionally feel ought to work, or what books say works for the construction trades, or what consulting companies claim are best practices. It should be a great session for people who want to supercharge their development teams.
Alas, things are really hot at Mobile Commons, so I can’t take advantage of the conference to attend some of the other great sessions. It’s back to work ASAP! But for those of you who can attend the full day, I envy your opportunity to hear people like Avi Bryant and John Resig speak…
¶ 2:00 PM1 comments
A Few Easy Ones from Raymond Smullyan
Many of you are familiar with the canonical ‘liar and truth teller’ puzzle. Raymond Smullyan is a logician who has taken the basic idea and expanded it to produce an immense variety of challenging puzzles. He has even used variations on the theme to illustrate Incompleteness Theory and other logic esoterica.
Here are a few easy ones to give you a taste of his sumptuous banquet:
Dr. Tarr is a psychologist with the Department of Health. Her job is to inspect asylums to determine whether they are in compliance with the law. Asylums have Doctors and Patients. In a compliant asylum, all the doctors are sane and all the patients are insane. Clearly, an asylum with an insane doctor or a sane patient is Not A Good Thing.
Sane persons are correct in all of their beliefs. Insane persons are incorrect in all of their beliefs. Both sane and insane persons are scrupulously honest: they always state what they believe to be the case. Unfortunately, the asylums are very modern and do not use identifying devices such as uniforms, ID tags, or other devices to show which persons are doctors and which are patients. Nor is it possible to know whether a person is sane or insane by any means other than questioning them.
One day, after inspecting a number of asylums, Dr. Tarr was having a drink and cigar with her good friend Professor Feather. The professor found her work interesting and asked her to recount some of her findings.
“Well,” said Dr. Tarr, “at the first asylum I visited, I met an inhabitant who made a single statement. I immediately took steps to have them released.”
“Wait,” interjected the professor, “so you’re saying this person was not an insane patient?”
“Of course,” replied Dr. Tarr.
Professor Feather thought for a moment, then asked “How is that possible? This sounds like the old Liar and Truth Teller puzzle. This person either told the truth or they lied. But there are four possibilities for any person in an asylum: Sane Doctor, Insane Patient, Insane Doctor, or Sane Patient.
“Even if you knew whether they were lying or telling the truth, that would only narrow the matter down to two possibilities. For example, if they told a truth such as ‘two plus two equals four’, you would know that they were Sane. But how would you know that they were a Patient, not a Doctor?”
Dr. Tarr replied with a chuckle “I agree that I could not have deduced what to do based on an inhabitant saying ‘two plus two equals four’. But in this case, the patient was quite intelligent and thought of a single statement which could establish the fact that only a Sane Patient could make that statement.
“I’m sure if you think about it, you could construct such a statement. Name a statement which could only be uttered by a Sane Patient.”
…
Dr. Tarr and Professor Feather shared a chuckle over that one. Then the professor took a more serious tone. “But have you ever had to remove a Doctor from an asylum?”
“Yes,” said Dr. Tarr sadly, “it has happened. Doctors do go insane once in a while. Recently I had just such a case. As it happened, I was visiting an asylum for the very first time and the first inhabitant I met made a single statement. I immediately had the inhabitant transferred to a special institution for former Doctors.”
“Don’t say it!” exclaimed the professor, “I want to work it out for myself…”
…
“Another time,” continued Dr. Tarr, “I was visiting an asylum which had been placed on probation for irregularities such as Insane Doctors and Sane Patients. I asked an inhabitant ‘Are you a patient’, and she said ‘yes’.”
“What did you do next?” asked Professor Feather. “Did you need to do any more investigating?”
…
“I’m glad you worked that out. Another asylum was on probation and I decided to ask the very same question of the first inhabitant I met. This time, when I asked ‘Are you a patient,’ he replied ‘I believe so…’.” Do you think I knew enough to close the asylum?
Professor Feather thought about this one for a very long time.
Off Topic: 1977 was an interesting year
I often think back to 1977. It seemed like such an amazing year to me at the time. In retrospect, that isn’t really surprising, because in 1977 I turned fifteen and fifteen year-olds have a large capacity for amazement and wonder.
I just ran across another interesting thing from 1977, a speech by then-President of the United States, Jimmy Carter:
Tonight I want to have an unpleasant talk with you about a problem unprecedented in our history. With the exception of preventing war, this is the greatest challenge our country will face during our lifetimes. The energy crisis has not yet overwhelmed us, but it will if we do not act quickly.
It is a problem we will not solve in the next few years, and it is likely to get progressively worse through the rest of this century.
We must not be selfish or timid if we hope to have a decent world for our children and grandchildren.
We simply must balance our demand for energy with our rapidly shrinking resources. By acting now, we can control our future instead of letting the future control us.
Two days from now, I will present my energy proposals to the Congress. Its members will be my partners and they have already given me a great deal of valuable advice. Many of these proposals will be unpopular. Some will cause you to put up with inconveniences and to make sacrifices.
The most important thing about these proposals is that the alternative may be a national catastrophe. Further delay can affect our strength and our power as a nation.
Our decision about energy will test the character of the American people and the ability of the President and the Congress to govern. This difficult effort will be the “moral equivalent of war” — except that we will be uniting our efforts to build and not destroy.
I know that some of you may doubt that we face real energy shortages. The 1973 gasoline lines are gone, and our homes are warm again. But our energy problem is worse tonight than it was in 1973 or a few weeks ago in the dead of winter. It is worse because more waste has occurred, and more time has passed by without our planning for the future. And it will get worse every day until we act.
The oil and natural gas we rely on for 75 percent of our energy are running out. In spite of increased effort, domestic production has been dropping steadily at about six percent a year. Imports have doubled in the last five years. Our nation’s independence of economic and political action is becoming increasingly constrained. Unless profound changes are made to lower oil consumption, we now believe that early in the 1980s the world will be demanding more oil that it can produce.
The world now uses about 60 million barrels of oil a day and demand increases each year about 5 percent. This means that just to stay even we need the production of a new Texas every year, an Alaskan North Slope every nine months, or a new Saudi Arabia every three years. Obviously, this cannot continue.
We must look back in history to understand our energy problem. Twice in the last several hundred years there has been a transition in the way people use energy.
The first was about 200 years ago, away from wood — which had provided about 90 percent of all fuel — to coal, which was more efficient. This change became the basis of the Industrial Revolution.
The second change took place in this century, with the growing use of oil and natural gas. They were more convenient and cheaper than coal, and the supply seemed to be almost without limit. They made possible the age of automobile and airplane travel. Nearly everyone who is alive today grew up during this age and we have never known anything different.
Because we are now running out of gas and oil, we must prepare quickly for a third change, to strict conservation and to the use of coal and permanent renewable energy sources, like solar power.
The world has not prepared for the future. During the 1950s, people used twice as much oil as during the 1940s. During the 1960s, we used twice as much as during the 1950s. And in each of those decades, more oil was consumed than in all of mankind’s previous history.
World consumption of oil is still going up. If it were possible to keep it rising during the 1970s and 1980s by 5 percent a year as it has in the past, we could use up all the proven reserves of oil in the entire world by the end of the next decade.
I know that many of you have suspected that some supplies of oil and gas are being withheld. You may be right, but suspicions about oil companies cannot change the fact that we are running out of petroleum.
All of us have heard about the large oil fields on Alaska’s North Slope. In a few years when the North Slope is producing fully, its total output will be just about equal to two years’ increase in our nation’s energy demand.
Each new inventory of world oil reserves has been more disturbing than the last. World oil production can probably keep going up for another six or eight years. But some time in the 1980s it can’t go up much more. Demand will overtake production. We have no choice about that.
But we do have a choice about how we will spend the next few years. Each American uses the energy equivalent of 60 barrels of oil per person each year. Ours is the most wasteful nation on earth. We waste more energy than we import. With about the same standard of living, we use twice as much energy per person as do other countries like Germany, Japan and Sweden.
One choice is to continue doing what we have been doing before. We can drift along for a few more years.
Our consumption of oil would keep going up every year. Our cars would continue to be too large and inefficient. Three-quarters of them would continue to carry only one person — the driver — while our public transportation system continues to decline. We can delay insulating our houses, and they will continue to lose about 50 percent of their heat in waste.
We can continue using scarce oil and natural to generate electricity, and continue wasting two-thirds of their fuel value in the process.
If we do not act, then by 1985 we will be using 33 percent more energy than we do today.
We can’t substantially increase our domestic production, so we would need to import twice as much oil as we do now. Supplies will be uncertain. The cost will keep going up. Six years ago, we paid $3.7 billion for imported oil. Last year we spent $37 billion — nearly ten times as much — and this year we may spend over $45 billion.
Unless we act, we will spend more than $550 billion for imported oil by 1985 — more than $2,500 a year for every man, woman, and child in America. Along with that money we will continue losing American jobs and becoming increasingly vulnerable to supply interruptions.
Now we have a choice. But if we wait, we will live in fear of embargoes. We could endanger our freedom as a sovereign nation to act in foreign affairs. Within ten years we would not be able to import enough oil — from any country, at any acceptable price.
If we wait, and do not act, then our factories will not be able to keep our people on the job with reduced supplies of fuel. Too few of our utilities will have switched to coal, our most abundant energy source.
We will not be ready to keep our transportation system running with smaller, more efficient cars and a better network of buses, trains and public transportation.
We will feel mounting pressure to plunder the environment. We will have a crash program to build more nuclear plants, strip-mine and burn more coal, and drill more offshore wells than we will need if we begin to conserve now. Inflation will soar, production will go down, people will lose their jobs. Intense competition will build up among nations and among the different regions within our own country.
If we fail to act soon, we will face an economic, social and political crisis that will threaten our free institutions.
But we still have another choice. We can begin to prepare right now. We can decide to act while there is time.
That is the concept of the energy policy we will present on Wednesday. Our national energy plan is based on ten fundamental principles.
The first principle is that we can have an effective and comprehensive energy policy only if the government takes responsibility for it and if the people understand the seriousness of the challenge and are willing to make sacrifices.
The second principle is that healthy economic growth must continue. Only by saving energy can we maintain our standard of living and keep our people at work. An effective conservation program will create hundreds of thousands of new jobs.
The third principle is that we must protect the environment. Our energy problems have the same cause as our environmental problems — wasteful use of resources. Conservation helps us solve both at once.
The fourth principle is that we must reduce our vulnerability to potentially devastating embargoes. We can protect ourselves from uncertain supplies by reducing our demand for oil, making the most of our abundant resources such as coal, and developing a strategic petroleum reserve.
The fifth principle is that we must be fair. Our solutions must ask equal sacrifices from every region, every class of people, every interest group. Industry will have to do its part to conserve, just as the consumers will. The energy producers deserve fair treatment, but we will not let the oil companies profiteer.
The sixth principle, and the cornerstone of our policy, is to reduce the demand through conservation. Our emphasis on conservation is a clear difference between this plan and others which merely encouraged crash production efforts. Conservation is the quickest, cheapest, most practical source of energy. Conservation is the only way we can buy a barrel of oil for a few dollars. It costs about $13 to waste it.
The seventh principle is that prices should generally reflect the true replacement costs of energy. We are only cheating ourselves if we make energy artificially cheap and use more than we can really afford.
The eighth principle is that government policies must be predictable and certain. Both consumers and producers need policies they can count on so they can plan ahead. This is one reason I am working with the Congress to create a new Department of Energy, to replace more than 50 different agencies that now have some control over energy.
The ninth principle is that we must conserve the fuels that are scarcest and make the most of those that are more plentiful. We can’t continue to use oil and gas for 75 percent of our consumption when they make up seven percent of our domestic reserves. We need to shift to plentiful coal while taking care to protect the environment, and to apply stricter safety standards to nuclear energy.
The tenth principle is that we must start now to develop the new, unconventional sources of energy we will rely on in the next century.
These ten principles have guided the development of the policy I would describe to you and the Congress on Wednesday.
Our energy plan will also include a number of specific goals, to measure our progress toward a stable energy system.
These are the goals we set for 1985:
—Reduce the annual growth rate in our energy demand to less than two percent.
—Reduce gasoline consumption by ten percent below its current level.
—Cut in half the portion of United States oil which is imported, from a potential level of 16 million barrels to six million barrels a day.
—Establish a strategic petroleum reserve of one billion barrels, more than six months’ supply.
—Increase our coal production by about two thirds to more than 1 billion tons a year.
—Insulate 90 percent of American homes and all new buildings.
—Use solar energy in more than two and one-half million houses.
We will monitor our progress toward these goals year by year. Our plan will call for stricter conservation measures if we fall behind.
I cant tell you that these measures will be easy, nor will they be popular. But I think most of you realize that a policy which does not ask for changes or sacrifices would not be an effective policy.
This plan is essential to protect our jobs, our environment, our standard of living, and our future.
Whether this plan truly makes a difference will be decided not here in Washington, but in every town and every factory, in every home an don every highway and every farm.
I believe this can be a positive challenge. There is something especially American in the kinds of changes we have to make. We have been proud, through our history of being efficient people.
We have been proud of our leadership in the world. Now we have a chance again to give the world a positive example.
And we have been proud of our vision of the future. We have always wanted to give our children and grandchildren a world richer in possibilities than we’ve had. They are the ones we must provide for now. They are the ones who will suffer most if we don’t act.
I’ve given you some of the principles of the plan.
I am sure each of you will find something you don’t like about the specifics of our proposal. It will demand that we make sacrifices and changes in our lives. To some degree, the sacrifices will be painful — but so is any meaningful sacrifice. It will lead to some higher costs, and to some greater inconveniences for everyone.
But the sacrifices will be gradual, realistic and necessary. Above all, they will be fair. No one will gain an unfair advantage through this plan. No one will be asked to bear an unfair burden. We will monitor the accuracy of data from the oil and natural gas companies, so that we will know their true production, supplies, reserves, and profits.
The citizens who insist on driving large, unnecessarily powerful cars must expect to pay more for that luxury.
We can be sure that all the special interest groups in the country will attack the part of this plan that affects them directly. They will say that sacrifice is fine, as long as other people do it, but that their sacrifice is unreasonable, or unfair, or harmful to the country. If they succeed, then the burden on the ordinary citizen, who is not organized into an interest group, would be crushing.
There should be only one test for this program: whether it will help our country.
Other generation of Americans have faced and mastered great challenges. I have faith that meeting this challenge will make our own lives even richer. If you will join me so that we can work together with patriotism and courage, we will again prove that our great nation can lead the world into an age of peace, independence and freedom.
—Jimmy Carter, “The President’s Proposed Energy Policy.” 18 April 1977. Vital Speeches of the Day, Vol. XXXXIII, No. 14, May 1, 1977, pp. 418 – 420. (via)
def formatted_zip_code(digits) case digits.size when 4 then "0#{digits}" when 3 then "00#{digits}" else digits end end
This code reads pretty much as the author would have explained how to handle the “digits” variable: If it only has four digits, pre-pend it with a zero. If it only has three digits, prepend it with two zeros. Simple and to the point and move on. Save the clever code for something that matters.
The Ruby Way is the perfect second Ruby book for serious programmers. The Ruby Way contains more than four hundred examples explaining how to do everything from distributing Ruby to functional programming techniques like the Y combinator.
The author of this code was an Agnostic. He didn’t mind using a case statement instead of if-elsif-elsif, he paid attention to the features of his chosen programming language, but he didn’t have strong convictions about there being One True Way to express every set of choices.
His code “Just Worked.”
Donning The Hair Shirt
The Agnostic’s code carried on, quietly working, until one day another programmer chanced upon it. Our second programmer was an Ascetic. Ascetics believe in code that can do powerful things with a small set of core axioms, like recursion and first-class functions.
The Ascetic spotted a bug: What if “digits” only had two digits? The objective of the code was clearly to have at least five digits, with leading zeros. The Ascetic cracked his knuckles and went to work.
def formatted_zip_code(digits) y { |rec| lambda { |str| str =~ /....(.)+/ && str || rec["0#{str}"] } }[digits] end
And all was well for a short time.
Toiling in the Stacks
The Ascetic checked his code in, where another programmer, a Librarian, reviewed it. She saw immediately that it could and should be re-written:
def formatted_zip_code(digits) digits.rjust(5,'0') end
Librarians believe that there is a library for everything, and good languages have huge libraries providing lots of built-in functionality. Programming is the art of searching the libraries for the one magic incantation that does exactly what you want.
And for a short time, all continued to be well.
Purity of Essence
One day, management hired a senior programmer with much experience working in the bowels of BigCo. He was brought in to provide “Adult Supervision” for the programming team. He went right to work, reviewing the code base and compiling a list of sins against his religious convictions. He was an OO Purist.
I am told that a cathedral built by Purists is beautiful to behold, constructed lovingly of small bricks, no more than 50 lines per class, no more than 10 classes per package, no more than two instance variables per class, no more than one level of indentation per method, no more than one dot per line, and absolutely no else clauses.
The Purist considered ifs, cases, and even shortcut booleans to be deficiencies in code, places where the proper approach—and indeed to only approach—is to use polymorphism and dependent types.
The Purist seized upon the twice-rewritten code as an opportunity to show how such a thing ought to be written:
def formatted_zip_code(digits) ZipCodeDigitFactory.new(digits).to_formatted_string end
Alas, space does not permit me to show you all of the subclasses of Digits he composed, one for each possible length of string. For example:
class FourZipCodeDigits < BaseZipCodeDigits def to_formatted_string "0#{self.to_s}" end end
I have also omitted his ZipCodeFactory that would take a normal string and figure out which particular subclass of BaseZipCodeDigits to construct.
(I am told that a cathedral built by Purists is beautiful to behold, constructed lovingly of small bricks, no more than 50 lines per class, no more than 10 classes per package, no more than two instance variables per class, no more than one level of indentation per method, no more than one dot per line, and absolutely no else clauses.)
Of course, the Librarian, Ascetic and the Purist hated each other with a passion fueled by the narcissism of small differences into a raging fire of religious cleansing. Much politicking and fighting broke out over the code.
Meanwhile, the Agnostic carried on, quietly coding while the others bickered over how to properly rewrite what he would write. One day, he noticed that some unit tests were failing and raised the issue in Campfire.
The Return of the Agnostic
“Hey,” he asked, “What happened to that piece of code? It was for zip codes, it was only supposed to pre-pend one or two zeros when importing zip codes from CSV files. Anything with fewer than three digits is supposed to be an invalid code. Empty strings shouldn’t be converted to five zeros, as far as I know.”
“What’s up with that?”
The Librarian, Ascetic, and Purist were silent for a moment, and then immediately resumed arguing, this time over whether #rjust should have another parameter, whether the regular expression in a recursive routine should be changed, or whether the simplest thing was to simply change the method for the EmptyDigits, OneDigit, and TwoDigits classes.
The Agnostic listened for a moment, tried to interject a few times, then sighed and reached for his text editor.
Update: Reviewing the comments made elsewhere, I see that this post fell into the Fizzbuzz Trap: By quoting a programming problem—no matter how banal and contrived—the article was bound to provoke a huge amount of dicussion around the correct way to solve the problem, while ignoring the point of the post. This is my fault, I should have known better than to post a snippet of code. As many of you have noted, the post is not about the Agnostic or his code, it’s about the dynamic of programmers eager to rewrite code in their own image, and the hypothesis that our (I am equally guilty of this behaviour) motivation for doing so is to emphasize the small differences between ourselves and others.
For no matter how good or bad the Agnostic’s code is, why did the Librarian rewrite the Ascetic’s code? Why did the Purist rewrite it again? When they discovered that the Agnostic’s code actually met some requirement, why weren’t they talking about documentation, or the process around tests? Why were they all—including the agnostic—eager to rewrite it one more time?
Seriously, the post is not about whether the Agnostic should have documented his code, or where the zip code validation should live. However, I should have known that the moment I included a piece of code to provide local colour, the resulting debate over its fitness was inevitable.
¶ 11:31 AM52 comments
Monday, May 12, 2008
Show, Don't Tell
Jeff Atwood is so right, I practically shouted “Slamma-lamma-ding-dong” when I read this line:
So what, then, are the alternatives to XML? One popular choice is YAML. I could explain it, but it's easier to show you. Which, I think, is entirely the point.
Now, I don’t mean, “Jeff Atwood is right that YAML is better than XML.” Well, I believe it is better than XML for a lot of things, but which things and how often and he didn’t exactly say that any ways.
What I actually mean is that Jeff is absolutely right that some things should not be explained, they should be directly experienced. It’s better to show them than to try to explain them.
Things that involve changes to human behaviour do not lend themselves to explanation. You have to try things. Or observe people trying things. Trying to explain it just doesn’t work, even though we humans have a huge and futile desire to try—including writing weblogs just like this.
Think about user interfaces. Imagine yourself traveling back in time to the eighties—last century!—and trying to “explain” Excel to someone who was a master of Lotus 1-2-3. They have seen a mouse in the computer store—it came with its own card and you configured jumpers to set the interrupt so it wouldn’t conflict with their extended memory.
Alas, I cannot explain why some combinations of software and hardware—like a TabletPC running OneNote or an iPod touch—simply work without putting one in your hands to try.
Now you are going to explain why they will be more productive pushing a plastic bar of soap around their desk instead of banging out slash commands at high speed? Are you crazy?
The only way this person will consider Excel is if you show them Excel. And I speak as a man who was there. At one time, Excel was so good that people would switch from their PCs with 1-2-3 to Excel on a Macintosh just to get Excel. Until, for some mysterious reason, Microsoft brought out Excel on Windows and the Windows version could use 8MB of RAM while the Macintosh version was limited to 1MB of RAM. Dunno why.
Or how about software development. What do you mean releasing software every two weeks or every month? It takes three to four months just to plan a release around here! And hey, that “better search” thingie you were droning on and on about? How much better can searching the Internet really be? Why would anyone care?
But when people see iterative development in action, when people use the Internet, and when people watch Google’s stock price… they get it, immediately.
The interesting thing is this: things that are easy to explain are things that fit with our incomplete and wrong mental models of how the world works. We have built a whole UI industry around trying to match our guesses of how people think, like imagining that an icon of a pair of scissors will tell people that clicking there will cause whatever they have selected to vanish and be held in some invisible suspension, waiting for them to click the icon that looks like a bottle of Kindergarten glue.
I am going to stop trying to explain that you should not try to explain some things to people. You don’t have to trust my word on the subject: Open your eyes and observe for yourself. When things involve human behaviour, it’s better to show than to tell.
¶ 10:05 AM10 comments
Tuesday, May 06, 2008
Why Apple is more expensive than Amazon
Let’s say you would like to listen to one of the most amazing performances ever made, Glenn Gould’s 1981 recording of Bach’s Goldberg Variations. And let’s say you have figured out the DRM is a really terrible idea, so you would like the hear it on high-quality MP3s.
The good news is that there are a number of places to legally purchase the right to download DRM-free MP3s. Lots of music from the major labels is available on Amazon, and it costs the same or less per track than Apple’s iTunes Music Store (“iTMS”), and you can find more DRM-free tracks on Amazon than on iTMS.
For example, Bach: Goldberg Variations, BWV 988 on 256-bit DRM-free MP3 is just $9.99 from Amazon. The same album is also $9.99 from Apple, but you get DRM. And there are tons of tracks on Amazon that are actually less expensive than on iTMS, so you get better music for less money without the DRM hassle. So is Apple screwing the customers?
In a word, no.
The reason you can find more music on Amazon at a lower price is that the Record Labels want it that way. Do you think they charge Apple and Amazon the same price for each track and Apple simply charges you more and pockets the difference as a higher markup? The labels would like you to think that, but they actually charge Amazon less for each track, and that’s how Amazon can charge you less.
Do you think Apple insists on the DRM but Amazon has the vision to see that the future of music is DRM-free? Do you think Jeff Bezos is a better negotiator and he was able to get a better price per track than Steve Jobs? Without putting up with DRM?
Really? How does that work, when iTMS is now the third-largest music retailer in the United States? How does the lower-volume store get better selection with fewer hassles and negotiate lower prices from its suppliers? When Steve Ballmer—not an easy man to intimidate—asked them for music to put in his Zune marketplace, these nice people extorted a $5 tax on each Zune sold from him. So how did Amazon get such a sweet deal?
Price fixing is how.
The major labels want nothing more than to break Apple’s dominance of the digital music business. They spin it as a good thing. More retailers means more competition, which is good for consumers. But let me ask you: if Amazon selling music for 89 cents a track is good for consumers, why isn’t iTMS also selling music for 89 cents a track good for consumers?
It would be good for consumers, but it wouldn’t be good for the music labels. The reason it wouldn’t be good for the music labels is that they really don’t want consumers paying 89 cents a track for DRM-free music. They want consumers to stop using iPods and start using devices with DRM that the labels can control.
They want consumers using devices in proprietary silos like old-fashioned cell phones, where you pay for the track, you pay for the bits transferred over the air, and then you pay all over again when you want to use a few seconds of the track as a ring tone.
As soon as they can break this pesky iPod-iTMS-iPhone nonsense, the labels want to get back to dictating what you pay and how often you pay. The labels want to do business with people like Microsoft. Microsoft gets it: all the people who bought music using MSN music? They can buy it all over again at the Zune store.
Do you think that the MP3 genie is out of the bottle and will never go back? You haven’t been paying attention to digital video media. The movie folks have succeeded in making DRM a standard for movies on DVD, and it is even worse on BlueRay. Have you seen the hoops a Microsoft PC has to go through to play video these days? Each piece of hardware has to promise to be a good boy and not let you actually do anything with the bits without permission.
The movies people have imposed harsher DRM on movies, and the music labels like the look of that.
The only—I repeat only—reason the labels allow competing stores to have DRM-free tracks is that it’s the only way to get music onto an iPod. Think about that for a moment: Apple’s dominance of the music player business is the actual reason you can buy a DRM-free track from Amazon. If anybody else had a substantial chunk of the player market, the labels would be busy trying to make the other player’s DRM the standard.
Imagine a world where every online store sells DRM-free music encoded in open licensable formats. In such a world, any player can play music purchased from any store, and any store can sell music which is playable on all players. This is clearly the best alternative for consumers, and Apple would embrace it in a heartbeat.
If the big four music companies would license Apple their music without the requirement that it be protected with a DRM, we would switch to selling only DRM-free music on our iTunes store. Every iPod ever made will play this DRM-free music.
I know, you’re going to bring up Apple’s DRM. Let me ask you a question: who do you think wanted DRM on iPods? Apple? Don’t make me laugh. Apple built a nice little business selling iMacs using the slogan “Rip. Mix. Burn.” They would love to keep building their nice little iPod business on the back of DRM-free music.
Think about this: If you buy a 32 GB Apple iPod touch from Amazon for $472.54, do you think Steve Jobs stays awake all night worrying about whether you will buy tracks from Apple or from Amazon?
If you answered yes, then you understand that Apple would be delighted to offer DRM-free music for the same price as Amazon. Or even less, since the profit selling you an iPod can subsidize their on-line store.
I personally answered “no,” because in my opinion, there are only three threats to Apple”s iPod business: Someone will actually out-design a music player and make that is actually better designed, cell phones will become the dominant music players, or someone else establishes a DRM standard that locks Apple out of playing downloaded music. I am not going to worry about anyone making nicer music players, I think we see what Apple is doing about the cell phone business, and now we understand what Apple is doing about the DRM business: If nobody can establish a DRM business, if nobody can lock you into one player, then nobody can take the music business away from Apple simply by getting into a back room and doing secret, monopolistic deals.
I’m looking at you, Sony and Microsoft. If the whole world has DRM-free music, you have to compete with iPod by building better music players. Sony, at least, has a chance. And if the whole world can sell DRM-free music, then Amazon and the like would have to compete with iTMS by building a better music store. Except, of course, they don’t have to compete with iTMS because the labels are colluding to place Apple at a disadvantage.
It’s delightful that for the moment, we have a choice of where to buy DRM-free music. It’s wonderful that today, we can legally purchase the right to listen to a lot of major label music on DRM-free MP3s. But let’s not kid ourselves. If the labels break Apple, this will not last. The genie will go right back into the bottle.
Buy what you like, where you like. But remember why things are the way they are. Apple is more expensive than Amazon because the labels want you listening to music on a Zune.
Update: Thanks for the links, John and Jeff. I spotted an interesting idea in the comments on Jeff’s post: the labels may not succeed in breaking iPod, but if they can break iTMS, they might be able to salvage the ability to set arbitrary prices.
One of the things they really hate about iTMS (alongside letting you burn your own CDs, transfer the music between computers, and share your music over a LAN) is that all music costs exactly the same. Breaking iTMS will restore the biggest weapons they have against artists. That has been discussed before, I recall Joel Spolsky’s Price as Signal.
Management saw this general-purpose mail reader and said, “since this mail reader is popular with normal people, we must now pimp it out to ‘The Enterprise’, call it Groupware, and try to compete with Lotus Notes!”
To do this, they bought a company called Collabra who had tried (and, mostly, failed) to do something similar to what we had accomplished. They bought this company and spliced 4 layers of management in above us. Somehow, Collabra managed to completely take control of Netscape: it was like Netscape had gotten acquired instead of the other way around.
“Groupware” is all about things like “workflow”, which means, “the chairman of the committee has emailed me this checklist, and I’m done with item 3, so I want to check off item 3, so this document must be sent back to my supervisor to approve the fact that item 3 is changing from ‘unchecked’ to ‘checked’, and once he does that, it can be directed back to committee for review.”
Nobody cares about that shit. Nobody you’d want to talk to, anyway
The hallmark of an architecture astronaut is that they don’t solve an actual problem.
Groove had some early success selling secure networks to the military-industrial complex, but didn’t make much of a ripple outside that niche. Their real success was in getting bought by Microsoft, which brought Groove’s designer and chief architecture-astronaut Ray Ozzie to the role of “Chief Software Architect” at Microsoft…
Ray Ozzie just can’t stop rewriting this damn app, again and again and again, and taking 5-7 years each time. And the fact that customers never asked for this feature and none of the earlier versions really took off as huge platforms doesn’t stop him.
Buying a company that makes shit that nobody cares about—nobody you’d want to talk to, anyway—just so you can replace your product leadership and vision with theirs and so that you can stop building your products that people actually care about and start building shit that nobody will care about…