Wednesday, February 3, 2010

Eva Cassidy

I'm probably late to the game with this one, since most of her recordings date from the late 1990's, and her album skyrocketed to number 1 in England around 2000, but I have just discovered an amazing musician.

Eva Cassidy grew up just outside Washington DC in Bowie, MD. She struggled with being extremely shy, and didn't like to be in the spotlight. She sang as a background singer for other musicians, and occasionally played at Blues Alley in DC. She recorded demos that she sent to labels, but her talents were too wide ranging. Record labels had a hard time imagining how to sell an artist that excelled a jazz, folk, pop/rock, R&B, and gospel.

In 1996, after some success collaborating with Chuck Brown on "The Other Side" and releasing a live album from some gigs she did at Blues Alley, she moved to Annapolis, MD and took a job painting murals at elementary schools. The summer of 1996 she was experiencing hip pain that she assumed was from using the stepladder at work. X-rays revealed she had cancer throughout her body. A few short months later, at the age of 33, she died.

Eva had a beautiful, clear voice, and for being extremely shy and afraid of the spotlight, she poured herself and her passion into her performances. Just search YouTube for videos, watch them, and you'll see what an amazing talent she had.

Her fame and success has come posthumously. When a DJ in England played her song on the radio, her album became a smash hit, and more and more people have been discovering her music. Perhaps part of the attention her music has gotten is because of her tragic story, but I believe her music stands on its own, and I'm glad to have discovered it.

Saturday, November 21, 2009

The Great Chef: A Parable

There was once a boy who loved food. He would sit for hours and read anything that had to do with food and cooking, including the instruction manuals for the kitchen appliances. The boy began to cook by trying out simple recipes. He would make the same recipes over and over and over, until he understood how each part contributed to the whole. His father noticed the boy's near obsession with cooking, and arranged for the boy to apprentice a chef.

Though the chef was not particularly masterful, he was a good chef. The boy was enthralled. He studied every minute detail of the kitchen, every movement of the chef. He studied the way the chef assigned tasks to the others that worked in the kitchen. He studied the way the chef chose his ingredients, and prepared his recipes. The boy became familiar with every tool at the chef's disposal, and eagerly did every job assigned to him, from chopping vegetables to mopping the floor.

Eventually, the boy became a man and he decided to enter cooking school. The first few years were boring drudgery to him, and he learned almost nothing. He had already experienced the inner workings of a disciplined kitchen, and he had continued to be a voracious reader of anything to do with food and cooking. However, in the later years of cooking school a new world was opened to him. He learned cooking techniques only few in the world understood. He learned the potent and exotic flavor of each spice. He learned the magic and the music of cooking.

Delicate dishes were like a symphony, each part had its purpose, and when everything came together the person eating it shared in some great truth, it was almost...mystical. The man had such a profound and heartfelt appreciation for food and cooking, that he found he couldn't even explain it to anyone else. In fact, the only people he could explain it to were others who had the same deep appreciation for food and cooking.

The man excelled at cooking school. His instructors and professors loved him because he was a passionate student. He eventually felt as though his professors were his peers, instead of his teachers. He even taught them a few things as he experimented with creating some truly unique recipes.

Finally, the man graduated from cooking school with the highest honors that could be achieved. He had become a master craftsman, an artisan. He had become The Great Chef. He struck out on his own to start a restaurant. His restaurant soon gained acclaim as everyone recognized his genius. Reservations had to be made over a year in advance.

The Great Chef decided that he would try something that would tax his skills to the breaking point. He had always toyed with the idea of creating this one dish that everyone said was impossible to create. He set his mind to it. If he cooked the tomatoes just so it would bring out the flavor he desired, and that would combine perfectly with the mushrooms. The combination of spices would perfectly complement the other ingredients. He sought out only the freshest meats and vegetables that were at the peak of ripeness, and at great expense.

All of The Great Chef's life's preparation had led up to this moment. By following his finely tuned intuition, he had created a recipe where no single ingredient could be removed without causing the flavor of the whole dish to collapse, because each ingredient depended on the others to draw out and complement its flavors. He only had to make the recipe once to know that it was perfect. He had done the impossible! He had proven beyond any doubt that he had no equal, and in the process he had created a new branch of the culinary arts.

One day, a man came to have dinner at The Great Chef's restaurant. He wasn't a connoisseur but he liked to try strange new things, and when someone told him The Great Chef's new dish was the best, he had to have it. He had made a reservation a year ago, and had come in from out-of-town expressly for this purpose. When it came time to order, the man said he would like to try the new dish, but as he read the description he said, "Oh...I don't like tomatoes. Can you make it without the tomatoes?"

Friday, November 20, 2009

The Programming of Philosophy

Just recently I watched Rich Hickey's presentation from the JVM Languages Summit 2009. It is a very interesting and thought provoking presentation, and well worth viewing. In it he takes from philosophy an understanding of time, state, and identity and applies it to the design of computer programming languages and models for concurrency.

Rich's presentation is also a further proof that no science (to include computer science) is philosophically or religiously neutral1. Computer science in particular is one of the more "philosophical" sciences. We model and reason about information in its purest and most elemental forms. We learn De Morgan's laws in CS classes for goodness sake!

The connection between philosophy, religion, and computer science is illustrated best in the field of artificial intelligence, where we must answer questions like:

  • What is intelligence?
  • Are human brains nothing more than biochemical computers?
  • Can an electronic computer model intelligence accurately?

I find it telling, that most AI researchers today punt on these issues. They have moved away from trying to define and model some theory of general intelligence, and moved towards statistical techniques, and creating agents that "act rationally" by imitating human behavior. However, even taking a pragmatic approach2 there is still a philosophical underpinning. For instance, take Jeff Hawkins work at Numenta, which I have written about previously, clearly there are influences of Empiricism.

We each have our own worldview, and our worldview not only influences the way we model the world, but it also limits our model of the world. Programmers are fond of talking about how the programming language you use limits the way you think about solving a problem3. We encourage each other to learn multiple languages especially from different paradigms (declarative, functional, object oriented, imperative, etc.) to gain new ways of solving problems. We have arguments about which languages model the world better. Is action (functional languages) primary or is existence/state (object oriented) primary? In other words which came first God existing, or God creating? You could even liken the debate about static versus dynamic typing to a debate about absolute versus relative morality. Can we possibly come up with a system of rules beforehand that are applied in every situation, or is that too rigid? ... OK maybe that last analogy is pushing it a bit... :)

I like what Rich has done. He acknowledges that his philosophy of state and time has come from Alfred Whitehead. Perhaps there are more lessons that can be learned from philosophy and applied to computer science. Or perhaps if we are explicit about our philosophical underpinnings and follow them to their logical conclusions we will gain some useful insights.

Footnotes:

1 This will most assuredly set some people afire, but I do not see a distinction between philosophy and religion. They both answer questions we have about the nature of the universe, the limits and proper use of reasoning, etc.

2 Pragmatism is a branch of philosophy, by the way.

3 Again from philosophy! See "Wittgenstein philosophy of language"

Friday, October 30, 2009

Simplicity and Complexity in Software

Avdi Grimm wrote "Simplicity is Complicated" where he argues that simplicity isn't simple. It brought to mind a few pet peeves of my own.

I think I agree with what Avdi has to say, but I might couch it in different language and come at it from the complexity side of the issue. I also have some opinions on simplicity in programs, which basically boil down to readability.

I like to think of complexity as being of two kinds: essential, and accidental. Accidental complexity is complexity that is introduced by the way in which you solve the problem. It is complexity that is unnecessary, and that could be removed by solving the problem in a more elegant fashion. Essential complexity, however, is complexity that is inherent to the problem, and cannot be reduced no matter how you solve the problem.

I had this conversation with a coworker recently. We were working on several reports for a Rails application. We were discussing whether it would be better to have a single controller with sixteen actions, or sixteen controllers with one action each. This is an example of essential complexity. If you have sixteen reports, then you are going to have sixteen "somethings," there is just no way around it. This is like Avdi's example of a pocket of air trapped under plastic, if you squeeze on the actions, then sixteen controllers will pop up somewhere else.

Then when it comes to simplicity in programs, my view is to reduce the accidental complexity as much as possible, and also to stick to the conventions and idioms of your language as much as possible. Obviously, there would be no innovation if we only stuck to conventions, but as much as possible, a Ruby programmer should be able to read and quickly understand a Ruby program. Consider these two examples from Avdi's article:

Example 1


sum = 0
i = 0
while i < times.length
  time = times[i]
  # parse / manipulate the time
  sum = sum + time
  i = i + 1
end

Example 2


def average_time_of_day(times)
  sum = times.map(&:to_time).inject(&:+)
end

I don't think that Avdi is necessarily arguing for this viewpoint, but he says that "[Example 1] uses language constructs that are familiar to almost all programmers, not just Ruby programmers," and that this can be considered a form of simplicity. While it's true that one might see that as a form of simplicity, I think the most important thing when writing a Ruby program should be writing it in a way that it is easy for Ruby programmers to understand.

When a Ruby programmer sees Example 1, he has to stop and think about what is going on, because it is not idiomatic Ruby. When he sees Example 2, he can immediately grasp the essence of what the code is doing. This is more an issue of readability than simplicity.

I'm not saying that the Ruby programmer grasps it easier because it is more terse. A Java programmer would look at Example 2 and perhaps be a bit befuddled. What I'm saying is that a Ruby programmer grasps it easily because it is idiomatic Ruby. I do not think it would be appropriate to write something like Example 2 in Java.

I would not advocate writing Java code with Ruby (like Example 1), nor would I advocate writing Ruby code with Java. Stick to the idioms and conventions of the language you are working within. And to those who say, "Well some Ruby programmers wouldn't easily grasp the essence of Example 2," I say, "You mean newbies?" Tough. They should master their tool. They should read more code written by others. That's part of being a professional programmer.

So to summarize, the distinction between essential and accidental complexity is, I think, a useful and important one in thinking about complexity of code. Second, to me the issue isn't so much simplicity as readability, and the key to readability is to stick to the idioms of your language as much as possible.

Wednesday, October 28, 2009

H1N1 "Swine" Flu

I have been confused about H1N1. The news reports that 1,000 people have died from it, but is that 1,000 out of 1,000 or 1,000 out of 17 million? There is no context to it. They report hyped up stories about a person dying from H1N1, but then it turns out the person did not die from H1N1 but from "complications"--where their immune system was compromised and they got an additional infection. You hear about how 60% of the hospitalizations and deaths are occurring in those under 65, when with the seasonal flu it is usually the reverse (i.e. 60% of the serious cases are in those over 65).

Then if you're like us, you hear about H1N1 infections in friends and friends of friends, and they're not dying. You hear about school classrooms where 5-6 kids at a time contract it, yet there are no follow up reports about schools where half of the kids have died...apparently they are recovering from the infections without much fanfare. You hear about doctors telling their patients that they do not need to get confirmation that they have H1N1, because they would treat it the same either way. So much for tracking the "deadly" pandemic as it spreads like wildfire across the nation.

Many health professionals are still seriously urging people to get vaccinated, but are saying that H1N1 is presenting in about the same way as the seasonal flu. Although there are some (perhaps disconcerting) differences from the seasonal flu, it is not some super deadly virus ravaging the earth's population.

The US Federal Government's Flu.gov site has a page about H1N1. Here are the highlights (if you trust the government ;) ):

  • About 70% of the people who have been hospitalized have had one or more medical conditions that placed them in the "high risk" category.
  • People over 64 do not appear to have an increased risk of complications.
  • Although there have been hospitalizations and deaths, the vast majority of people who have contracted H1N1 have recovered without medical treatment.
  • H1N1 spreads the same way as seasonal flu (coughing, sneezing, person-to-person contact). It is not an airborne super contagious version of the flu.

The CDC also has a page about the characteristics of H1N1. More highlights:

  • Between April and July of 2009, it is estimated that about 1 million people had been infected with H1N1, and of those 1 million about 5,000 people had been hospitalized and about 300 had died.
  • H1N1 occurs most often among 5-24 year olds.
  • Hospitalizations occur most often among 0-4 year olds.
  • Deaths occur more often among 5-24 year olds. But again the deaths usually occur in cases where there are other underlying medical conditions.

Another whole set of issues, which I won't go into here, has to do with the vaccination. All I can say is that as far as I know there is nothing "different" or "untested" about this vaccine. It is prepared the same way as the vaccine for the seasonal flu, it just contains a different strain of the virus. There is more information about the vaccination at flu.gov.

I am not a health professional, statistician, or expert in any way. I may have misinterpreted something, if so, let me know. This is just food for thought, and perhaps a voice of balance among the hype.

Tuesday, October 27, 2009

Google Reader gets magic

Something I have long desired in a feed reader is magic. Not just magic, but personalized magic. I was all excited with Google Reader's "auto" sorting, which turned out to be less than useful. The problem was that it was not personalized.

I had even thought about creating a "smart" reader. Something as simple as a naive bayes filter seemed like it would be a step in the right direction. If I can teach a computer to recognize spam, then why can't I teach it to recognize the feed articles that I enjoy? I had experimented with such a smart reader, but it was never enough of a problem for me to pursue it far enough.

Enter Google Reader's new "magic" sorting. Unlike the previous "auto" sorting, this one is personalized. It takes into account the articles that I "like", "star" and "share." I've been a big fan of true personalization. Sites like digg and reddit (and postrank in the blogosphere) are nice, but I don't want to read what the "community" finds interesting--which is often puerile 13 year old male content--I want to read what I find interesting.

Finally a feed reader seems to have what I'm looking for: true personalization. I plan on using this feature, and I hope I won't be disappointed.

Friday, July 10, 2009

metric_fu, rcov, and rspec

I've been setting up metric_fu on one of my projects, and I ran into a problem where the rcov report was not including my specs. (This is an old project that has both Test::Unit tests and RSpec specs.) I did lots and lots of digging, and was baffled that no one has mentioned that they cannot run coverage reports for their specs using metric_fu. It seemed like an obvious and heinous oversight on the part of metric_fu.

As always, I suspected that I was missing something. Test::Unit tests can be run individually from the command line like ruby path/to/test, and metric_fu appeared to be trying to do this with the specs, but when I did ruby path/to/spec I got nothing.

I actually looked at the metric_fu specs to discover this, and it is probably very obvious to any serious RSpec user, but I discovered that I needed to add require "spec/autorun" to the top of my spec_helper.rb file. This includes the magic that makes ruby path/to/spec work, and makes rcov include my specs in its report when it is invoked by metric_fu.