Monday, September 08, 2008

Critique of Zittrain's "The Future of the Internet and How to Stop It"

One book that the technorati have been talking about recently (ok, not so recently... it took me a while to write this article) is Jonathan Zittrain's The Future of the Internet and How to Stop It. For a book written by a co-founder of the Berkman Center and someone who is a remarkably good speaker, I found the work to be disappointing. The book's argument is not convincing and the writing seems to lack discipline, often wandering from one loosely related subject to another.

Zittrain's main point is that the security failings of generative technologies will push consumers to buy more restrictive, and supposedly safer, devices. This claim has a number of problems with it. The first is that tethered devices are not safer or more secure than generative ones -- in fact, normally the opposite is true. Compare the number of vulnerabilities in the Windows operating systems vs the number in Linux or BSD operating systems. Or bugs in Internet Explorer vs bugs in Firefox. This claim is even more dubious the more control the manufacturer has over the device: Richard Stallman points out in his response to Zittran that the iPhone's remote kill-switch makes the iPhone "designed for remote attack by Apple."

The second problem with Zittrain's principal claim is that a consumer has no incentive to prefer a non-generative device. Since non-generative devices are less secure than generative ones, any purported advantage that the non-generative device manufacturer could claim is lost. There is empirical evidence to support the belief that consumers prefer generative devices --Stallman cites the number of jailbroken iPhones as an example. Roger Grimes adds in his response: "It’s hard to say that closed systems are taking a more prominent role when open examples abound. Even the 'closed' systems he mentions are becoming more open thanks to competition and customer demand."

Even if, for the sake of argument, locked-down devices were somehow more secure than generative devices, consumers wouldn't necessarily migrate to non-generative appliances because users rarely make purchasing decisions based on security. Most computers are purchased because the user is comfortable with the platform or because he thinks that the computer is pretty or because that particular computer is necessary to run some type of software. Rarely will a run-of-the-mill consumer take into account a record of operating system vulnerabilities or the pros and cons of different systems architectures when deciding between OSX and Windows.

There are other shortcomings of the book besides the weakness of the main argument. For one, Zittrain mistakes generativity as being a zero-sum game: something is either generative or it isn't. There is a continuum of generativity: for instance, Linux is more generative than Windows XP, but Windows XP is more generative than Windows Vista. It is a fallacy to simply assume that all products fall into one non-generative bucket or the other generative one.

For a book whose title suggests solutions to the problems with the Internet, Zittran's ideas underdeliver. Virtual machines, extra-legal incentives, data portability and network neutrality are all things that are familiar, and have been, to policymakers and programmers for a while. In a book such as this which only worries about theoretical overtures and not about the detailed technical implementation, more out-of-the-box, grander thinking and proposals would have been welcome.

The book has a couple of chapters that feel decidedly out of place. The final chapter regarding privacy and the chapter exploring Wikipedia both don't seem to fit in to the framework of the book. That being said, both are certainly worthy of scholarship on their own merits. I particularly found the chapter on privacy engaging, if not particularly relevant to the rest of the book.

Zittrain's book is still worth a read: it addresses areas of concern in today's Internet and references much interesting material. The end result, however, is unconvincing and disappointing -- keep a few grains of salt handy when reading.

=========================================
REFERENCES / FURTHER READING

Jonathan Zittrain
http://bostonreview.net/BR33.2/zittrain.php
"Protecting the Internet Without Wrecking It"

Richard Stallman
http://bostonreview.net/BR33.2/stallman.php
"The root of this problem is software controlled by its developer"

Bruce M Owen
http://bostonreview.net/BR33.2/owen.php
"As long as flexibility has value to users, suppliers will have incentives to offer it"

Roger A Grimes
http://bostonreview.net/BR33.2/grimes.php
"Fixing Web insecurity requires more than a caring community"

Hal Varian
http://bostonreview.net/BR33.2/varian.php
"Ultimately, the best protection is an informed buyer who demands openness"

Susan Crawford
http://bostonreview.net/BR33.2/crawford.php
"In the eyes of many exiting institutions, security isn't a problem -- it's an opportunity"

David D. Clark
http://bostonreview.net/BR33.2/clark.php
"We need to develop a socially embedded online experience"

Jonathan Zittrain
http://bostonreview.net/BR33.2/zittrainresponse.php
"The best solutions don't assume a zero-sum tradeoff between security and generativity"

Coverage on BoingBoing

Ars Technica review and interview

Friday, August 29, 2008

Watch High Quality YouTube Videos by Default

Explained here. Man, I missed the boat on this one... it's been out for half a year!

Cool Gmail Feature -- Periods do not Matter

It's true: john.doe@gmail.com is the same email address as johndoe@gmail.com as far as Gmail is concerned. And to think that everyone makes such a big fuss about making sure you have that period in the right place when they give out their emails...

This feature is documented in Gmail help here. Gmail even idiot-proofs this feature by having a link to the docs when you receive an email at a different address from the one you registered (see photo).

Some have used this feature to their advantage to reduce spam or create multiple accounts on a web service that all send mail to the same Gmail address.

Friday, August 22, 2008

Thoughts on Facebook and Privacy (or Lack Thereof)

After watching a DEFCON 16 presentation about the vulnerabilities in social networks, I reflected further upon Facebook and the privacy it offers you and me, which is close to nil. Your guarantees to privacy on Facebook depend on a multitude of assumptions, all of which are quite poor. [B]

First, you are trusting that the Facebook developers have implemented the privacy controls correctly such that there is no inadvertent information leakage on the site as a result of bugs. I write code for a living, and let me tell you, bug-free code does not exist. Facebook, like other applications, has had its share of bugs to scramble to fix in the past (including at least one truly amateur mistake) and the future will be (and the present is) no different.

Second, you are assuming that you can configure the myriad privacy options correctly such that every piece of information on your site is accessible to only those that you want it to be. Are you really sure that marking one person as only being allowed to see your limited profile and specifying that picture as globally viewable, for example, will turn out the restrictions you desire for the correct people? How can you tell which preferences override which? It would certainly be tedious to register other accounts (or use friends') and test various combinations of privacy features against their profiles and I am not aware of anyone that does this.

Third, anyone that can see your information is capable of leaking it to the public. [A] With the addition of every friend you are increasing the chance that your pictures, contact info, videos, etc. will be posted and shared outside of the Facebook walled garden. It is simply not possible that each of your 500 friends is not susceptible to give away information that you thought was just between you and them, especially when they have some kind of (monetary or otherwise) incentive to do so. The scenarios of a rival political party digging up dirt on a candidate and gossip magazines researching what someone did last night both come to mind.

Fourth, all of your information can be accessed by any Facebook engineer or executive who choses to do so. The engineers likely need access to real-world pages to debug their code, and the managers can order information from a compliant underling (if Facebook doesn't have internal tools set up already for them to access this information). And let's not forget everyone else that works there (sales, PR, HR, etc.) who can request your personal information as a favor from an engineer friend.

Fifth, just as with any other website, information on Facebook can be subpoenaed in a trial. Facebook, needing to comply with the law, will gladly turn over your personal information to any judge who so wishes.

Sixth, let's not forget the countless ways Facebook could involuntarily compromise your information. A malicious hacker could slurp down personal data off the site. A Facebook employee could negligently leave an unencrypted disk drive with your information on it in a public place. Etc.

The only conclusion is this sound advice: don't put anything on Facebook that you don't want to be exposed to the world. Because chances are, sooner or later, it will be.

Footnotes:

[A] This is, of course, assuming that your group of Facebook friends can not be considered 'the public.' With the amount of friends some have, and especially one's willingness to accept any request that comes their way and fire out friend requests at random, this distinction begins to blur.

[B] I was going to add this post to my Facebook Sucks article but it became too long and I thought it deserved a post of its own.

Updates:

Here is a post for those that want a HOWTO for micromanaging their privacy settings on Facebook. (Even Schneier likes it).

Here is a Slashdot story about a court demanding Facebook information pursuant to a case

Tuesday, August 19, 2008

DEFCON 16

DEFCON 16 was awesome, as expected. Some highlights:
  • The first presentation I went to was called "Hacking in the Name of Science." Here a bunch of University of Washington grad students and a professor discussed the sweet research they are doing, almost all of which has been in the news (Implicating 'downloading' printers to the RIAA monitors, RFID ghost proxies, TCP information leakage, voting machine vulnerabilities, TrueCrypt vulnerabilities, implantable medical device hacking, ISP injected ads, etc.). They discussed the difference between just hacking and what you need to do in an academic setting to study what anyone else would call hacking. They encouraged attending academic security conferences, such as ACM CCS, NDSS, IEEE Security + Privacy, HotSec and Woot
  • A talk entitled "Satan is on my Friends List" detailed the security vulnerabilities in OpenSocial-enabled websites. These guys demonstrated some hilarious things, including using a CSRF DOS attack: using an img tag placed in an html-enabled form that displays on a page, you can automatically logout anyone that sees that img by pointing the img's src attribute to the logout page. The speakers talked about how the socnet widget applications space is essentially a security free-for-all: apps hacking personal information, apps hacking other apps, etc. An opt-in security model for javascript safety in apps exacerbates the problem. An amusing conclusion to the talk was the speakers' impersonation of another security researcher on social networks which fooled his colleagues and family alike.
  • Locksport enthusiast Eric Schmedl gave a talk that had some amusing anecdotes about cloak-and-dagger spying. Mary Lou McFate (NRA infiltrator of anti-gun groups), reconstructing passwords from audio of keystrokes, and multiple phone bugging technologies were discussed.
  • Fyodor gave a talk on nmap, the tool he created and how he used it to scan a large subset of the Internet. He also presented some new features of the tool, including traceroute, ping, and netcat-like functionality... what can't it do?
  • I briefly stopped in on a talk called "Taking Back Your Cellphone" which plugged the site HowardForums as an excellent resource for phone modification.
  • The activity that I took part in for a fair share of my time there was the Lockpicking Village. I bought a set of lockpicks, and tried my skills on a variety of locks lying about the room. I also listened to talks on how to crack certain types of locks, including masterlocks (use coke can shiv, patterns for figuring out combo).
  • Probably the most interesting thing that happened at DEFCON nobody got to see: a judge ordered a group of MIT students not to talk about hacking the Boston Subway system. This was rather pointless because 1) the presentation was distributed on CD before the gag was ordered 2) the ban was lifted after the conference 3) MIT's student newspaper put the presentation up on its site
  • Other cool things: the badge, the mystery box
  • Didn't see these presentations, but I looked at them on the CD:
    • "The Death of Cash" features a preview of a world without cash. People are turning to credit because it is more convenient, banks love it because of better profit margins, government loves it because it makes you easier to track. (Note: Illegal to transfer $10,000 in/out of the country without declaring it). This is getting worse with stupid legislation (Patriot Act). Also, national security risk: electronic outages now mean that people can't get access to cash (even more troublesome as electric grid becomes less reliable). Strong crypto might be the basis of a future E-payment system. Advice: keep some cash on hand for emergencies, use non-cash as little as possible. thowlett@netsecuritysvcs.com says the presentation can be downloaded at www.netsecuritysvcs.com/presentations/defcon16/ but I don't see it there...
    • An introduction to ham radio called "Ham for Hackers"
    • A presentation on Javascript obfuscation that goes over the following methods: ASCII/Unicode escapes, XOR (ASCII/encoding), string splitting, simple encryption, non-obvious variable and function names, member enumeration, whitespace encoding/decoding
    • Another presentation on SCADA systems that made me have nightmares
    • A HOWTO on SSL cookie hijacking by Tor developer Mike Perry: insert an img tag with src mail.yahoo.com into an unencrypted connection and read their cookie, then save that cookie to cookies.txt and read their email (over SSL, if you want!)
    • OCR tools: tesseract, jocr, ocrad
    • A presentation similar to "Satan is on my Friends List" for Google Gadgets
Update:
Good photos of the event can be found here

Monday, August 18, 2008

Proposal: Free Parking through Self-Booting

San Francisco is a tough city to park in, so I've been scheming up some ways in which to get free parking... here's one thing I've come up with, but haven't had the guts to try yet.
  1. Buy four boots (or more formally, wheel immobilizers).
  2. Park in a tow-away parking zone.
  3. Affix one boot to each wheel of your car.
  4. Laugh at the people figuring out how to tow your car away seeing that they can not drag your car along on its back wheels nor wheel the car up onto a platform.
  5. Return to your car at your leisure, detach boots, drive away.
Some things to consider:
  • Boots are somewhat expensive, so the whole cost-efficiency of this scheme needs to be taken into consideration (price of tickets, if you plan to pay them, price of parking, risk of having car destroyed by angry tow truckers).
  • I'm not sure what kinds of contracts tow truckers have with the city, private establishments, etc. If they are not liable for any harm that comes to your car, this probably isn't such a good idea, as the towers have no incentive to not damage your car trying to toe it away.
  • Not paying tickets can bite you in the ass if the ticket-giver somehow manages to figure out your Vehicle Identification Number, usually found etched in various places in the car. Unpaid tickets can come up when you try and re-register your vehicle.
  • Boots can be pried off... I'm sure this isn't the only way
UPDATE: Nothing to do with booting, but here's another way to get free parking in San Francisco, courtesy of Black Hat

Monday, August 11, 2008

HOWTO vertical display (X, Nvidia)

Here is how to get your monitor looking something like this (not my monitor, btw):




























Put this line as an option in the "Device" section of /etc/X11/xorg.conf: Option "Rotate" "CCW" Then, restart X with Ctrl+Alt+Backspace. Afterwards, start up sudo nvidia-settings and shuffle the screens around in X Server Display Configuration so that they are properly aligned. Be sure to press the Save to X Configuration File button.

Found via this forum thread and a tip from Arash.

Update:
Following is an xorg.conf file to get 2 Dell 2407 monitors in a T formation (with one on the left vertical and one on the right horizontal aka Rajiv-style). This setup has a few problems, though...
1) The screens are flush at the top, which makes a window across both monitors look disjointed... not a huge problem, and could probably be solved by tweaking the config
2) Can't seem to get compiz-fusion to work
3) Using Xinerama instead of Twinview is waaaaay slower, especially when an object is on both screens
4) Just feels too unnatural... I'm going back to both screens horizontal
It's also a bit hard finding helpful forum posts on these things anyways because everyone seems to misuse the terminlogy (Xinerama, Twinview, etc.) and problems are very individual (Depending on video drivers, screens, etc.). Anyways, here's the xorg.conf:

Section "ServerLayout"
Identifier "Default Layout"
Screen 0 "Screen0" RightOf "Screen1"
Screen 1 "Screen1" 0 0
EndSection

Section "Module"
Load "glx"
EndSection

Section "ServerFlags"
Option "Xinerama" "1"
EndSection

Section "InputDevice"
Identifier "Generic Keyboard"
Driver "kbd"
Option "XkbRules" "xorg"
Option "XkbModel" "pc105"
Option "XkbLayout" "us"
EndSection

Section "InputDevice"
Identifier "Configured Mouse"
Driver "mouse"
Option "CorePointer"
EndSection

Section "Monitor"
Identifier "Configured Monitor"
EndSection

Section "Monitor"
Identifier "Monitor0"
VendorName "Unknown"
ModelName "DELL 2407WFP"
HorizSync 30.0 - 83.0
VertRefresh 56.0 - 76.0
EndSection

Section "Monitor"
Identifier "Monitor1"
VendorName "Unknown"
ModelName "DELL 2407WFP"
HorizSync 30.0 - 83.0
VertRefresh 56.0 - 76.0
EndSection

Section "Device"
Identifier "Videocard0"
Driver "nvidia"
VendorName "NVIDIA Corporation"
BoardName "GeForce 7900 GS"
Option "Rotate" "CCW"
Option "NoLogo" "True"
BusID "PCI:1:0:0"
Screen 0
EndSection

Section "Device"
Identifier "Videocard1"
Driver "nvidia"
VendorName "NVIDIA Corporation"
BoardName "GeForce 7900 GS"
BusID "PCI:1:0:0"
Screen 1
EndSection

Section "Screen"
Identifier "Screen0"
Device "Videocard1"
Monitor "Monitor0"
DefaultDepth 24
Option "TwinView" "0"
Option "metamodes" "DFP-0: nvidia-auto-select +0+0"
EndSection

Section "Screen"
Identifier "Screen1"
Device "Videocard0"
Monitor "Monitor1"
DefaultDepth 24
Option "TwinView" "0"
Option "metamodes" "DFP-1: nvidia-auto-select +0+0"
EndSection

Monday, July 21, 2008

Keep SSH connections from timing out, client-side

Put these lines in ~/.ssh/config

ServerAliveInterval 300
TCPKeepAlive yes

Sunday, July 06, 2008

txt2regex

txt2regex is an awesome tool that allows you to specify a regular expression in an interactive curses-based interface that is then printed out in a variety of formats, including English, vim, perl, etc. Perfect for when you know exactly what you want to match, but are not particularly knowledgeable about the idiosyncrasies of the current regex engine you're using.

Friday, July 04, 2008

Stop Spamming me with Corporate Birthday Cards

It is the time of year when my birthday is fast approaching and that means that I am receiving a few birthday cards, sometimes from parties from which I would not expect one. Some of these parties are not people, but corporations who happen to have my birth date on file for one reason or another.

In any other context, snail mail sent from a corporation to one's home mailbox for marketing purposes would be called junk mail or spam. Sunglasses Hut, et al. try and disguise the purpose of the letter (making you want to buy more of their products) by making the implication that they're corresponding out of consideration for you by politely remembering the celebration of your birth. Now, some may think that this is a genuine gesture of kindness, but I disagree. The entire point of a card is to remind someone that you are thinking about him or her and his/her particular situation. I find nothing personal or redeeming about being the recipient of a letter sent by a cron job at HQ once a year which was ordered by a marketing director that neither knows me nor has any reason to care about my circumstance save trying to extract more of my hard-earned cash out of my pocket.

In fairness I must note that, unlike most every other sender of birthday spam, Sunglasses Hut at least sent me a twenty-dollar gift certificate to their store. Considering that I don't need another pair of sunglasses and would hesitate to buy from SH again given this annoying practice, I find it small recompense for wasting my time and mailbox space with their spam.

I guess this can just be chalked up to another consequence of an age when more private parties are holding our personal data and are ever eager to exploit it for their own ends. It seems as there is no disincentive for corporations to send all the spam they want, I'll be receiving quite a few more cards from well-wishing chief marketing officers in the future.


bigshotcmo@sunglasseshut27:~$ crontab -l
# m h dom mon dow command
0 0 1 * * ./send_birthday_cards_for_month

...

db.execute("SELECT * FROM customer WHERE MONTH(birthday) = MONTH(NOW())).each do |customer|
Notifier.send_individual_card(customer)
end

...

Dear $customer.first_name,

Happy birthday! You are super special to us! Spend more money at our store!
Thanks for providing us with your birthday! Thanks to our expert DBAs and
comprehensive database backup policy, we're able to retrieve your personal
information on demand and sure to never expunge your data from our records.
Have a nice day!

Love,

Moneybags
CMO

Tuesday, June 17, 2008

HOWTO Swap caps lock and escape keys in Linux

Caps lock takes up way too much space on a keyboard for how little (never) one presses it. Esc is a very useful key that gets pressed a lot (especially for vi users) but is rather far away and takes more effort to press in the corner of the keyboard. Here is how to switch the functionality of the two keys (solution adapted from the xmodmap manpage) in Linux.

Create a file called .Xmodmap in your home directory. Put the following text in the file:

!
! Swap Caps_Lock and Escape
!
remove Lock = Caps_Lock
remove Control = Escape
keysym Escape = Caps_Lock
keysym Caps_Lock = Escape
add Lock = Caps_Lock
add Control = Escape

Next time you log in, these settings should stick. If you want to switch the keys manually instead of on startup, run xmodmap .Xmodmap to do so. Loading the file again after you have loaded it once will switch the keys back to their original functionalities.

Btw, an informative discussion of all of this X customization stuff is found in chapter 6 of Unix Power Tools.

Tuesday, April 29, 2008

Google Experimental Search

Today I stumbled across Google's experimental page which has some add-ons to search that can be enabled. "Keyboard shortcuts" kicks ass: it's basically a vi-like interface to search. j to go down, k to go up, / to search, etc. It's really quite slick.

Although Google says that you can only add one of these experimental features at a time, "Keyword suggestions" is an option that can be enabled via the Customize Google Firefox extension. "Keyword suggestions" is a great feature as well.

The "Alternate views" options , on the other hand, are a heaping waste of time. Even the search results for the example queries listed on the page are unintuitive and uninformative.

Google also offers keyboard shortcuts for a lot of other products (Gmail, Calendar, Docs, Reader, Maps, Video), detailed here.

UPDATE: I actually disabled the experimental features. The vi emulation was not helpful enough... I could scan the page visually faster than my fingers could keep up. Furthermore, I missed the utility of Firefox's "/" to search the text on the page fast on a Google search result page.

Friday, April 04, 2008

Searching SVN trees with Ack (for Ruby on Ubuntu)

Searching through a subversion tree with grep is a pain in the ass. It wastes time searching through files I don't want to look into and its syntax is inconvenient for the task. Fortunately, there is a tool called ack which is suited specifically for matching text in VCS trees (including svn trees). Here's how to set it up on Ubuntu Gutsy (apparently you won't need to do all this in the next Ubuntu release; there's a package for Hardy).

First, you're going to need some relevant libraries. sudo apt-get install perl-doc to start. Next, download the File-Next archive from CPAN. Extract the archive and cd into the directory, then use the series of commands perl Makefile.PL && make && make test && sudo make install to install it.

Now for ack itself. svn checkout http://ack.googlecode.com/svn/trunk/ ack-read-only to checkout the source tree from Google Code and cd into the directory. Now if you want to edit some of the types that are built into the program, here's where to do it. For example, I want to also search for haml files with the --ruby flag. I grep -R rhtml * to see that four files (actually, less, but let's go ahead and edit all of them anyways...) require modification. The ruby line in Ack.pm, for instance, now reads ruby => [qw( rb rhtml rjs rxml erb haml )]. (Types can also be set on the command line using the --type-add and --type-set flags). Once you're finished tweaking types, use the same perl Makefile.PL && make && make test && sudo make install command to install ack.

For extra credit, you can also add flags to a ~/.ackrc file that get executed upon each invocation of ack. Personally, I add the --ruby flag because it seems to be that .rb, .haml and .rhtml files are all that I'm searching for these days.

And voila! Now a simple ack -f gives me a listing of all the ruby files in my svn tree (and no vi swp files, svn files, log files, etc.). ack "regex" returns a grep-like search of the relevant parts of the subversion tree with the parts of the line that matched the regex highlighted. SWEET! Get more information on the command line with ack --help for more help, ack --help type for a listing of matching types.

Do you know how hard this would have been with find/grep/xargs? Well, tough. grep -RE "regex" * | grep -v svn | grep -v log | ...etc... searches all files in the tree and might exclude matching lines if the contain one of the strings being filtered out by the later grep instances. That syntax can be improved to a alternating regular expression with grep -RE "regex" * | grep -v -E \(log\|svn\) but it still has the same problems. grep also has an --exclude flag which can exclude certain filenames that match a glob from being searched (although the manpage would seem to imply otherwise), but it doesn't have regex capabilities. So maybe we can use find and xargs? Nope, a svn tree output will kill xargs, which will compain that the "argument line is too long" if too much gets sent to it: grep -E "regex" `find . -regex '.*\.\(rhtml\|rb\|haml\)' | xargs -0` Perhaps find's --exec flag could be of use? Well, only if you want to kill your computer with the overhead of creating a new grep process and forking and context switching a couple times (etc.) upon each file match... find . -regex "regex" -exec grep -E "regex" '{}' \; will really do your cpu in. Then there's the cumbersome grep -E "regex" $(find . -regex "regex" | grep -vE \(log\|svn\)) ... well, let's just say I'm glad I found ack at this point.

UPDATE:
Put --type-add=ruby=.haml in your .ackrc to add haml as a type dynamically.

Sunday, March 30, 2008

Amazon's Music Store on Ubuntu Gutsy

Unfortunately, there are some CDs that are so obscure nobody is seeding them on BitTorrent. One of these happens to be Hicksville by Celtic Cross. I decided to give the Amazon Music Store, where this CD is available for purchase, a shot.

On Ubuntu Gutsy, there are a few things you need to do to make this work. The first, of course, is to download the .deb package from this page. Install that with sudo dpkg -i amazonmp3.deb or sudo dpkg --force-architecture -i amazonmp3.deb if on a 64 bit system. You're also going to need a few Boost libraries: sudo apt-get install libboost-date-time1.34.1 libboost-thread1.34.1 libboost-iostreams1.34.1 libboost-signals1.34.1 If you're on a 32 bit system, launching the /usr/bin/amazonmp3 binary should now work (it also inserts an entry in the GNOME panel under Applications->Internet).

But for all you 64-bit'ers out there, there's a bit more work to do. Launching the binary fails with the message "amazonmp3: error while loading shared libraries: libgtkmm-2.4.so.1: cannot open shared object file: No such file or directory". This is because amazonmp3 needs 32 bit libraries, not 64 bit ones (see this thread). Download getlibs, a bash script which installs 32 bit versions of libraries on 64 bit systems. Install the package with sudo dpkg -i getlibs-all.deb and then run getlibs /usr/bin/amazonmp3 to install the 32 bit libraries. The program should now run without error.

The application, by the way, is quite minimalistic. I don't know why they put users through this trouble and don't just send you a tarball of the music files. I guess there might be some reason on other platforms where it integrates with other applications... not on Linux, though!

Wednesday, March 12, 2008

Why NIN's "Ghosts" Release Matters

Nine Inch Nails ushered in another landmark event in the slow march towards freedom of digital media recently when it released its newest work for free (gratis and libre) on its web site. NIN band member Trent Reznor has frequently been at the forefront of innovation in music and the surrounding areas and it is not at all surprising and very pleasing that it is him to be the first high-profile artist (to my knowledge) to release a major work under a Creative Commons license. However, not everyone seems to grasp the significance of what has happened here. In fact, not even the article that the Slashdot article links to reports the fact that the album has been released under a CC license and many other news outlets have neglected this important point as well. In this article, I'll give a summary of the events surrounding NIN's release of Ghosts I-IV and an analysis of its significance.

First, some history of the band: Nine Inch Nails has never been a conformist where promoting its music has been concerned. The history of their original ideas is impressive: breaking off from their label and releasing their work independently; encouraging fans at concerts to "steal" music; hiding USB drives for fans to find with new, unreleased songs on them; performing surprise concerts as part of an elaborate fantasy world constructed for fans and releasing Garageband samples for others to remix.

There is precedent for releasing music free (both gratis and libre) online. Most artists now have a myspace page or other limited Internet presence where one can listen to, but usually not download (or only download a small piece of) an album. Many low-profile artists have been releasing their music online for years under various licenses. Radiohead, arguably, has been the most famous band to release an album free of charge online (with In Rainbows last year). Radiohead allowed each customer to specify their own price for a full download of the album off of its site, even $0. It is estimated that Radiohead made many millions of dollars with this tactic.

Next, the facts about the Ghosts release. From the Nine Inch Nails website there are a variety of options for downloading the album, etc:
  • Free: The first 9 tracks from the Ghosts I-IV collection available as high-quality, DRM-free MP3s, including the complete PDF.
  • $5: All 36 tracks in a variety of digital formats including a 40 page PDF.
  • $10: Ghosts I-IV on two audio CDs in a six panel digipak package with a 16 page booklet. Pre-order, to be shipped April 8, 2008. INCLUDES immediate full download in a variety of digital formats.
  • $75: Ghosts I-IV in a hardcover fabric slipcase containing: 2 audio CDs, 1 data DVD with all 36 tracks in multi-track format, and a Blu-ray disc with Ghosts I-IV in high-definition 96/24 stereo and accompanying slideshow.
  • $300:



Nine Inch Nails also uploaded a torrent to the Pirate Bay of the first 9 tracks of the album (out of 36 total) with the following message:
Hello from Nine Inch Nails.

We\\\'re very proud to present a new collection of instrumental music, Ghosts I-IV. Almost two hours of music recorded over an intense ten week period last fall, Ghosts I-IV sprawls Nine Inch Nails across a variety of new terrain.

Now that we\\\'re no longer constrained by a record label, we\\\'ve decided to personally upload Ghosts I, the first of the four volumes, to various torrent sites, because we believe BitTorrent is a revolutionary digital distribution method, and we believe in finding ways to utilize new technologies instead of fighting them.

We encourage you to share the music of Ghosts I with your friends, post it on your website, play it on your podcast, use it for video projects, etc. It\\\'s licensed for all non-commercial use under Creative Commons.

We\\\'ve also made a 40 page PDF book to accompany the album. If you\\\'d like to download it for free, visit http://ghosts.nin.com/main/pdf

Ghosts I is the first part of the 36 track collection Ghosts I-IV. Undoubtedly you\\\'ll be able to find the complete collection on the same torrent network you found this file, but if you\\\'re interested in the release, we encourage you to check it out at ghosts.nin.com, where the complete Ghosts I-IV is available directly from us in a variety of DRM-free digital formats, including FLAC lossless, for only $5. You can also order it on CD, or as a deluxe package with multitrack audio files, high definition audio on Blu-ray disc, and a large hard-bound book.

We genuinely appreciate your support, and hope you enjoy the new music. Thanks for listening.

http://ghosts.nin.com
A little while after the release of the album and the spreading of the news, the NIN website got overloaded with requests, prompting Trent Reznor to post the following message there:
Update: The response to this album has been overwhelming, causing our website to slow to a crawl. We THOUGHT we were ready, but...
We've been adding more servers to accommodate the unexpected demand and we expect to be running smoothly in the next few hours. In the meantime, if you've had any problems with downloads from the Ghosts site, don't worry - you'll be able to use your download link again when the site is more stable. Thanks everyone for making this such an immediate success.

posted by Trent Reznor at 5:47 PM pst, from hong kong.
So why is the release of Ghosts significant? Because it's the most visible release of art under a Creative Commons license to date (by-nc-sa 3.0, to be exact). This means that Trent Reznor can not take you to court for distributing the music on, say, the Pirate Bay; it explicitly permits this kind of activity. All the license mandates is that if you use the work, you must credit the original author and you must release your new work that incorporates NIN's art under the same license. The license also prohibits any use of the work for financial gain by a third party (no selling the album on the street for five bucks a pop). This is in marked contrast to Radiohead, who did not specify the license that In Rainbows was under, so because of this ambiguity we must only assume that it is under a traditional copyright license. This means that Radiohead CAN take you to court for distributing the music if one day it decides that suing its fans is fashionable. Releasing art, especially music, in this fashion is going to become increasingly prevalent as more artists realize the benefits of instantly sharing art with the world via the Internet in preference to traditional distribution channels such as record labels. With computer technology, how fans use music is increasingly out of an artists' control. It is a much more amicable arrangement for the artist to indulge fans by releasing music in a way they find convenient (and, also, not sue them).

The release of Ghosts also establishes BitTorrent as a recognized distribution channel in which established artists can release their music. Frequently, the BitTorrent protocol and its users are denigrated in the media as "pirates" or "thieves." The fact that a respected artist is using BitTorrent in preference to direct download or a record label-sponsored distribution will legitimize this method of sharing in the eyes of many and heighten the profile of BitTorrent generally. Using BitTorrent was also a good move simply because it is a superior protocol for large files, as the slowness of the NIN website showed. Also, it is more convenient to use than having to click through the kind of omg-it's-free messages (or, more generally, an unfamiliar interface) that Radiohead made users weather to buy In Rainbows. Being so in touch with how music fans want to acquire their music definitely doesn't hurt NIN's publicity, either.

Reznor also proves that it is wholly possible to make a lot of money off of a free product on the Internet, something that many ill-informed pundits think impossible. Slashdot reports that the most expensive option sold out in about a day, netting Reznor $750,000. This is to say nothing of any of the other purchasing options, which also likely brought in a significant amount of revenue, possibly much more than the $300 dollar option. So why are people paying for something that they could more or less otherwise get for free? A few answers can be found in Kevin Kelly's essay Better Than Free. Kelly claims that the Internet has made copyable material infinitely abundant, and therefore impossible to charge money for. What can be charged for are what Kelly calls "generatives" -- things that can't be copied. He suggests 8 generatives from which money can be made in a world with Internet technology: immediacy, personalization, interpretation, authenticity, accessibility, embodiment, patronage and findability (convinience). By autographing records, NIN provides authenticity and personalization. By offering downloads off its site in a variety of digital formats, NIN makes money off of findability, accessibility and immediacy. And, of course, being an artist offering up works for free under a CC license NIN reaps the benefit of patronage: listeners loving what they are seeing and hearing and willing to pay for more of the same.

Another important point about this event is that all the data on NIN's site will eventually find its way out from behind the wall of authentication and payment and onto public networks. That is, users that paid for enhanced versions of the product will upload them to a BitTorrent tracker: here already are the ($5) FLAC versions of all 36 songs and some extras. It is often repeated that information wants to be free, as we can see here. What is not often repeated, but equally true, is that information wants to be convenient. Fans of In Rainbows proved this yet again when they uploaded the album to BitTorrent (humorously leading some ignorant columnists to castigate users for "stealing" it -- how can you steal something if it's free and able to be infinitely copied?).

In conclusion, the experimental release of Ghosts on the Internet under a Creative Commons license and for free is a milestone event for a variety of reasons. It is the first high-profile musical release that is free, both as in freedom and as in beer. It made NIN a whole lot of money, proving that artists can survive in the Internet era (even without performing). And it enhances the profile of the BitTorrent protocol as a distribution mechanism and reinforces some well-understood properties of Internet-based information distribution. Hopefully other artists will follow NIN's example and release their work in a similar manner.

===============================
Further reading:
  • Reznor decries fact that people see Radiohead as first to release free online, says industry won't follow his lead anytime soon because it's inept. (Link)

Thursday, February 21, 2008

Ruby (vs Python): a preliminary assessment

I've been using Ruby for a little over a month now. While this hasn't been enough time to explore the depths of the language, it has given me ample time to evaluate how I feel about some of the more superficial aspects of Ruby. There are some things I like about it, a few things I don't care about, and a lot of things I don't like. In some aspects it is quite similar to Python, my favorite programming language. In the following sections I lay out what I do, kinda, and don't like about Ruby, sometimes in comparison to or in contrast with Python to put things in context.

Things I like about Ruby


Naming conventions are enforced The less surprises there are in code, the easier it is to read. I would be very surprised, for example, if a C VARIABLE_IN_ALL_CAPS were not a constant. It only takes one joker working on code to completely screw with convention and degrade readability of code for everyone else working on it. Ruby heads off this problem at the pass. Instance variables look like @this, class variables look like @@this, constants look like THIS, global variables look like $this, etc. This is a Good Idea. I can easily live without the flexibility to name my class h0We\/ER_I_want. This also makes the code easier to parse and syntax highlight.

Block Comments I'm not sure how Python missed the boat on this one. The "large chunks of code shouldn't be commented anyway, so take them out" and "get a decent text editor that can :50,70s/^/#/" and "that's what doc comments are for" school of thought just doesn't resonate with me. Too often there is some large chunk of code lying around that just isn't applicable anymore and quickly commenting it out is a temporary solution.

Constants There is just something about the assurance that certain variables are read-only that makes me sleep well at night. Otherwise, I need to worry about things getting overwritten, and that's no fun. I guess there's always CONVENTION to prevent this in Python, but that doesn't stop someone from breaking CONVENTION += 1

Examples are the norm in documentation Examples are the quickest way to learn about new code. However, the docs could benefit from some non-example elaboration most of the time. How is one supposed to figure out corner cases? I guess "examples first" goes along with the whole Ruby-has-no-formal-spec thing.

'case' syntax The syntax of Ruby's case statement (analogous to switch in other languages) is pretty rad. It's a great feature for when multiple properties of one variable need to be tested. The case statement accepts comparisons, ranges, regular expressions, etc. Very cool.

Things I could go either way on

Regular expressions built into the language Regular expressions are cool, and I use them a lot, but I just don't know if they have a place amongst the pantheon of hashes, lists and the like. They are convenient, but overuse might turn your code into *gasp* Perl. No one likes unreadable ASCII-splatter, although it's tough for Ruby to get that bad. Plus, half the time I am using regexes some other function might do just as well, like rindex. Maybe that's just my laziness that Ruby caters to.

Interned strings It's like a pointer, I get it. It saves memory over using a string object, cool. Was it really worth including in the language? Not sure. It seems like their most common uses, such as keys in hashes, could be implemented under the hood anyway (well, at least in a real language like Python where hash keys are immutable).

! and ? as legal characters in method names I can understand that does_this_work? is a natural way to read that a function returns a boolean. I get that destroy! suggests an internal change of state of the object. But then there's the problems. First, not every method that returns a boolean or changes an object's state is forced to use these constructs. If they were enforced like all-caps constants and @ before instance members, maybe I'd be more bullish on them. Second, what qualifies as a change of state can get kind of messy: maybe a method only conditionally changes its object's state; is an exclamation mark appropriate then? The exclamation mark can also be misread, especially if parentheses are omitted (looks an awful lot like a logical not operator, doesn't it?). And now for my nitpicky objections: ? and ! are harder to type than letters and vim doesn't auto-complete the full method name by default (it completes everything but the last character) if one of those characters is included.

Marriage to Rails On the one hand, it's nice to have a large support community for tools that one is likely to use. On the other hand, it's annoying to wade through a bunch of comments by people on forums and mailing lists that are completely irrelevant to what you're trying to do with the language. These people are normally exclusively concerned with getting their website up and running, aren't terribly gifted programmers and don't really care about the language per se. Some bloggers assume that any talk about Ruby is in the context of Rails because... well, isn't that what you're using it for? What else could you possibly do with Ruby?

Indentation Python has a unique indentation system. In most cases (Makefiles) whitespace indentation is a horrible idea, but Python manages to make it work. It reduces noise on the screen and is pretty intuitive. I'm not convinced that Python wouldn't be more effective, however, with a traditional bracket-defined indentation scheme which Ruby is close to. It's a toss-up for me.

Things I don't like about Ruby


TMTOWTDI There's more than one way to do it in Ruby, alright -- you're smothered with options. This is the dark path that leads to Perl. Take looping as an example. In Python, you have for and while. That's it. In Ruby, you have for, while, times, upto, downto, begin/end and each (there's probably more that I missed). What's wrong with for? It's really difficult to be intimately familiar with this many options. And this symptom doesn't just plague looping, it also plagues the standard library. Do we really need every one of <<, push and + to append to the end of an array? Why have both brackets and "end" to enclose a block? Has anyone ever used all three versions of defining a class method in any mood but malice and spite? I guess we can all take solace in the many ways in Ruby via active_support to compute the amount of bytes in a gigabyte: 1.gigabyte, 1024.megabytes, 1048576.kilobytes, etc.

Go with the Flow There is a prevailing attitude with Ruby users, especially in Rails, to favor convention over configuration. This means that tools that espouse this philosophy reward going with the flow and punish breaking out of the mold and customizing your applications. My attitude towards this philosophy is this: unless you are creating the most pedestrian and generic of applications, you are going to need to customize the application at some point. When that happens, it is much better to have a tool that allows flexibility than one that disdains it. Otherwise you are going to need to go down to the core of the tool to make minor changes to your application, and that will cost you in time and sanity.

Hashes are broken In Python, it's impossible to change the keys in a dictionary because those keys must be immutable when they go in. Python also nicely throws a KeyError when something you're looking for in a dictionary is not there. Ruby does neither of these things; the programmer is expected to maintain the immutability of hash keys. High-level languages are supposed to take care of important details like these for us humans who are busy thinking about other things. In fact, the Python FAQ lists this as an "unacceptable solution" for an alternative implementation of hashes: "Allow lists as keys but tell the user not to modify them. This would allow a class of hard-to-track bugs in programs when you forgot or modified a list by accident." Default return values aren't that much of a design travesty, but I still prefer the error. Besides, if you really want a default return value in python, you can just use setdefault when accessing the element that may or may not be there instead of setting a default value for the whole hash at creation.

Ranges are broken This absolutely baffles me. Why did Ruby not choose to incorporate Python's elegant slicing syntax and instead chose a less powerful and more confusing one? Why did Ruby choose to create an unnecessary class called Range when they just could have had a function called, oh I don't know, range that is much more powerful, simple and general and that returns lists/arrays? Why do you need to call range.to_a to convert your useless Range object to an array in Ruby when they could have just used a function like range and gotten to the point? Furthermore, why are there two ways to create ranges, .. (two periods) and ... (three periods) that look EXACTLY THE SAME! Argh.

Optional omission of syntax elements Sure, it's less typing in Ruby, but remember what I said earlier about less surprises equaling more readable code? It holds here as well. Is this_thing a variable or a function call? This also excludes the convenient syntax for introspection that calling function() without parentheses in Python affords. And the fact that sometimes you need the "do" keyword and sometimes you don't is also a design decision that just begs for unnecessary tripping over the syntax.

Inline control flow constructs When I first saw these, I thought "Wow! I can now do in one line what previously took me three in Ruby!" And then I started reading a lot of lines and wondering why they weren't executing. And then I read those lines a bit further and saw that they had conditional statements tacked on to the end of them. And then I vowed to never use them again. One example of how this can go bad is tacking on "and return" to the end of a long statement. If you're looking at the code, and not scrolling right far enough (and your lines are that long that you need to scroll, which may or may not be a good idea), it looks like the code falls through after every statement instead of returning. Confusing.

Different names for the same method find_all? What the hell does that do? Oh, it's the same as select. Collect? What's that? Oh, it's the same as map. Too bad I only found these things out after going to the documentation. Why can't one function just have one name, so we can all have a common point of reference? Oh, right, because Ruby "allows you to program in your natural language." Which means confusing everybody else, including myself.

Different precedence for seemingly identical operators ! binds more tightly than not. && and || bind more tightly than "and" and "or". This is incredibly confusing; why not just make them the same precedence? Changing one form to the other form when it is right near another operator whose precedence is between the two could alter the control flow of your code.

Inability to override = (and non-obvious performance gotcha) There is some fine print to go along with the "every operator is just a function" propaganda. One annoying exception to the rule is the = operator. Now, why would anyone want to override the equals sign? First let me point out that it's not just =, but also -=, +=, *=, etc. that also are incapable of being overridden, so it affects a substantial set of important operators that are literally expanded to x = x + y, etc. Now here's the kicker: these methods are orders of magnitude slower than their true method counterparts for arrays and strings. So I want to override += for arrays to have it call concat or << which are both efficient as a way of aliasing all +='s in the existing codebase. In C++ and other languages, this would be quite possible (never mind that you wouldn't be facing this problem in C++ to being with) but in C Ruby, a design decision has been made that no one can override the sacred = and therefore coders will inevitably trip over this performance gotcha. Why? I'm not sure... maybe this or that post may offer some insight. In any event, don't use += and its cousins for anything but numbers or risk serious performance hits (changing one to the other is further complicated by their difference in precedence... both behave differently within a conditional operator, for example. Grrr.)

Confusing operator overloading << is a way to print things out (a la C++), define a class method, and append to the end of an array. Only the last one makes sense to me; the other two seem out of place. Remember what I said about less surprises = better code readability? It's beginning to become quite a theme...

No list comprehensions [heavy_sigh for each_time_I_can_not_do_this in Ruby if I_am_particularly_exasperated] I guess there's always select and collect. Too bad I need to decide if I want all the items in the list or only a subset before I can select the correct method to use (instead of at the end in Python, where I can insert if statements if necessary). I also haven't discovered a way in Ruby (yet?) to do the related task of a one-line instantiation of a hash. In Python, this would be d = dict((x, None) for x in [1,2,3])

Perl-like operators << <=> and =~? Sorry, I just can't get into it. Keep it simple, please. Function calls with letters are good.

Lists and hashes are printed strangely puts {1=>2,2=>3,3=>4} gives me 122334 in Ruby. WTF? I thought I was dealing with a hash, not a number. print {1: 2, 2: 3, 3: 4} gives me {1: 2, 2: 3, 3: 4} in Python. puts [1,2,3] gives me numbers on separate lines in Ruby. print [1,2,3] gives me [1, 2, 3] in Python. The seemingly small detail that data structures are printed out exactly how they are written in code makes a world of a difference.

Strings are unintuitive Strings are iterated over by word, not by character in Ruby: "one two".each {|x| puts x} in Ruby outputs "one" and "two" on separate lines. Compare this to for i in "one two": print i in Python, which prints out a character on each line. To iterate over each character in a string in Ruby, you'll have to use each_byte (in which case you'll find that Ruby will print out numbers unless you convert the numbers with .chr... this problem also occurs when selecting a character from a string, as in str[5] even though the docs say otherwise) or each_char.

Bad decisions on naming Why is there a built in variable called $DEBUG? Doesn't everyone have a global variable called that in their program at some point or another? Well, overwriting this variable unknowingly will cause your code do very strange things, like disregard begin/rescue/ensure blocks. I found this out the hard way. Python's is __debug__. Who is going to create a variable called __debug__ in their program? Nobody, that's who. The closest thing Ruby has to a constructor is called initialize. Why so long? __init__ works fine, and programmers who failed literature can actually spell it.

Shortcuts for everything "p" for print. The attr family of keywords for attribute access. Why not just create usable constructs and stick with them, instead of inventing unwieldy constructs and then working around them with shortcuts?

Hype Ruby is definitely the flavor of the week in programming languages. This results in a bunch of n00bs flocking to the language when they want to learn to program. Now, I have nothing against people who want to learn how to program. In fact, I'm thrilled that anyone wants to take a little time to learn the art. But the experience of a community has benefits: better tools and better discussions. As a result the conversations in Ruby forums and mailing lists are generally of a lower quality than that on Python mailing lists which tend to be frequented by more knowledgeable, veteran coders.

Japanese Origins As an English speaker, I appreciate that most of the cutting-edge blog posts and PEPs and what not are in English. Ruby originated from Japan, so this is not the case there. It's frustrating for me to see a link like "the solution to your problem is here" only to be led to a page which to me might as well be in... well, Japanese. I am sure I would feel differently if I were Japanese, of course.

OSX/TextMate-centric community A large number of Ruby users use Macs. Not sure why, that's just the way it is. They also seem to like TextMate. Me? I hate Apple and love vim. The more people that use the tools that you use, the higher probability that someone has already solved the configuration problem that is bugging you. Although I will note that the default settings for Ruby in vim are very nice... there's at least one knowledgeable vim user writing Ruby out there.

Younger Language Python has been around since the late 80s. Ruby has been around since 1993 (both for certain definitions of "around"). Python has a head start on Ruby in terms of developer time. A more mature language is likely to have fewer bugs, more features, less experimentation and and more users. The same goes for libraries written for that language: a greater number of better-implemented libraries will be available to users of a language that has been around longer. All other things being equal, the older language has to win the stability and reliability battle.

Unfamiliar keywords Instead of try/catch (or except)/finally, Ruby has begin/rescue/ensure. Instead of continue, Ruby has next. Instead of else if or elif, Ruby has elsif. Instead of switch/case, Ruby has case/when. I guess every language commits this foul to some extent, but it's just one more thing to trip over.

Implicit returns Another Perlism that I despise. To me, a function looks like it doesn't return anything if it doesn't have the "return" keyword in there at some point. It's much easier to read (and maintain) code if the points at which a function could return something are explicitly outlined.

Things I don't have an opinion on... yet

Introspection/Reflection Haven't really dug that deeply into what Ruby can do here yet...

Package management The gems system vs letting apt-get do everything. Neither has failed me in any way thus far, but then again, I haven't really tried to do anything remotely complicated with either and I'm not a sysadmin presiding over a myriad of different configurations...

Threading Ruby doesn't support native threads. What are Python's options? This looks like a good article and what about Stackless Python?

Object Oriented stuff Namespaces, modules, Inheritance, etc. I'm sure there's some Python vs Ruby flamewar going on out there, I just have to find the thread...

Monday, January 07, 2008

Funny UNIX utilities

Some humorous UNIX utilities that brighten my day:
  • cowsay -- get a cow, etc. to do the talking
  • fortune -- witticisms, some more offensive than others (fortunes-off package contains more offensive fortunes, fortune -o invokes offensive fortunes)
  • banner -- big friggin letters

Printing with enscript

enscript is an awesome utility for printing text files; it kicks lpr's lame ass. Here are some examples of usage (more to come as the need arises):
  • Letter enscript --no-header --word-wrap example_file.txt
Also, navigate to localhost:631 on any system with CUPS installed in order to configure the default printer and such.

Friday, December 14, 2007

Learning Ruby from Python

I just started to pick up Ruby today (to install: sudo apt-get install ruby irb ri rubygems). Here are some things I learned along the way, coming from a Python mindset. The (very good and highly recommendable) references I looked at were (in order):
  1. Ruby in Twenty Minutes
  2. To Ruby From Python
  3. Ruby Essentials (free, on-line book)
  4. Important Language Features and Some Gotchas
Similarities
  • Brackets for arrays, braces for dictionaries (called hashes in Ruby)
  • Strong dynamic typing
  • Everything is an object, variables are just references
  • Exceptions are similar
  • No special line termination characters
  • # for single line comments
  • def to define a method, class to define a class
Differences
  • Interactive prompt: python => irb
  • Interactive prompt help: help(str.count) => help "String#count"
  • Interactive prompt reload: reload(foo) => load "foo.rb"
  • Command line docs: pydoc => ri
  • File extension: .py => .rb
  • Shebang line: #!/usr/bin/python => #!/usr/bin/env ruby
  • Indentation and blocks: : and tabs => either { } or end
  • Strings: immutable => mutable (can use freeze method for immutability)
  • Naming conventions: unenforced => enforced (ex. class names start with a capital letter, variables start with a lowercase letter)
  • Raw strings: r"blah" => 'blah'
  • Parantheses: mandatory => sometimes optional
  • Booleans: True, False => true, false
  • Null value: None => nil
  • Else-if statement: elif => elsif
  • Module import: import foo => require "foo"
  • Boolean conversion: 0, False, None and anything empty => Only nil and false
  • Doc generation: docstrings below things => regular comments above things
  • Output: print => puts (or print if you don't want a trailing newline)
  • Command line execution: python -c => ruby -e
  • Global Variables
  • Ranges: range(x,y) => x...y exclusive, x..y inclusive (.to_a to return array)
  • Slicing: arr[1:3] => arr[1...3] or arr[1..2] (inclusive)
  • Object initialization: __init__ => initialize
  • Object creation: a() => a.new
  • Ternary operator: if_true if statement else if_false => statement ? if_true : if_false
  • Substring matching: 'foo' in str => str['foo']
  • "Main": if __name__ == '__main__' => if __FILE__ == $0 ... end
Philosophical differences
  • Attribute access: direct access => method calls
    • Need getter and setter methods to access attribute outside class
  • Access permissions: convention by underscore => public, protected, private
  • Multiple inheritance: allowed => mixins
Stuff Ruby has that Python doesn't
  • Double quoted strings allow expression substitution #{} and escape sequences \t\n
  • You can re-open a class at any time and add more methods
  • Block comments: ==begin and ==end
  • Special variable characters (begins with...):
    • $ global
    • @ instance
    • [a-z_] local
    • [A-Z] constant (triggers warnings when reassigned)
    • @@ class
  • Arrays support some set operations
    • difference -
    • intersection &
    • union |
  • Method conventions (ends with...)
    • ! changes internal state of object
    • ? returns boolean
  • do keyword -- optional loop keyword (unless on single line)
  • Crazy for loop alternatives
  • General delimited strings
  • Case statement
  • Lots of options for string element access and string substitution and insertion
  • Regular expressions as first-order objects
  • Perl-like control flow constructs that can be tacked onto the end of an expression

Tuesday, December 11, 2007

"Why don't you write a Facebook Application?"

There is a lot of hype surrounding the newly released Facebook application platform. Developers are falling all over themselves to get a product rushed out the door, funding for Facebook apps is flowing in from VCs and you can even take a class in Facebook application development at Stanford. Amid all of this irrational exuberence, I find myself frequently getting asked why I don't write to it. Well, there are a lot of good reasons to stay as far away from the platform as possible. It's proprietary, unpredictable, not a level playing field in the least and crowded with unworthy offerings. My time and effort is much better spent somewhere else.

First of all, even if we assume for the sake of argument that I am interested in developing a Facebook app, the deck is stacked against me. Tim O'Reilly points out that there is a steep drop off in users after the first four or five most popular apps (the graph on O'Reilly's page is instructive). There are a few reasons for this. The first is that the door has largely closed on the willingness of users to add new applications or suggest them to their friends; the fad has come and gone. In other words, "[W]e must acknowledge that ... users have grown accustomed to a small subset of applications available to all users, and the exploratory period has come to an end... Facebook is all about communicating an image of yourself to your peers, and unless someone creates a truly captivating, innovative, or better F8 application, no one is going to adopt it on a whim." The quickest functional and moderately compelling apps to get out the door were the ones that users pounced on. The second reason for the disparity in users parallels the disparity in the finances and professionalism of the makers of the apps. Five of the top six apps right now are made by just two companies: Slide and RockYou!. [A] Making little flash widgets is essentially these companies' entire business and both of them are well financed. Amateur developers do not stand a chance against a small army of VC-backed Flash coders who do this for a living. [B] Any entry into the Facebook app market now is essentially futile.

The survivability of the Facebook platform is another issue. It bears some eerie similarities to "walled garden" initiatives past. Perhaps most illustrative is the case of AOL, whose proprietary platform, of course, nobody uses anymore. Should I really bother developing against a technology predicting that it won't survive 10 years? Perhaps, but I would rather write to a platform that is built on open standards. Jason Kottke explains: [E]
As it happens, we already have a platform on which anyone can communicate and collaborate with anyone else, individuals and companies can develop applications which can interoperate with one another through open and freely available tools, protocols, and interfaces. It's called the internet and it's more compelling than AOL was in 1994 and Facebook in 2007.
The fact that Facebook could change its platform or go out of business at any time is a disincentive to write a Facebook application. I don't like my creations functioning at the whims of Facebook or its investors; it's a better bet to go with an established, open platform.

I ran across a similar post on Facebook app suckiness that raised an additional reason not to develop a Facebook app. If, against all odds, your application is truly innovative and distinguishes itself in the crowd of petty profile pollution, you still are on Facebook's turf; that carries some important consequences. Specifically, Facebook could copy your idea with a feature that they subsequently build in to Facebook itself. It will be accessible to all users, not just the ones that choose to add it as an application, and there will be no use for your app anymore. Facebook could take your idea and reimplement it, thus sucking away all of your users, and there would be nothing you could do about it.

Then there is the embarrassing stigma of being in the company of Facebook application developers. The (many) applications are written by developers who want to jump on the Facebook hype bandwagon. Most of them are amateurs, and it shows. Take the Quizzes application, for instance (ranked 14th in most active users, so a reasonably popular app). It lacks basic functionality that one would expect in such an application: namely, the ability to see the correct answers after you take the quiz. It also creates a quiz that other people can take before you even indicate you are finished adding questions! Furthermore, I couldn't access the application at all today because, presumably, it is choking under the load that Facebook is sending to it (another all-to-frequent problem of these applications). Quizzes, admittedly, might be an application that one might use occasionally. I can not say the same about other applications, most of which can be broken down into four categories:
  • Horoscope
    • What flower are you? -- "Are you rose, lilly, foxglove, daffodil, nigella, sunflower, violet? Find out."
    • Birthstones -- "From the time gemstones were discovered, they were believed to have mystical powers and attributes that could be passed to the wearer. The red of ruby was fiery and passionate; cool blue sapphire was calm and composed. What's yours?"
    • Psychic Breeze - Psychic Readings and Fortune Telling -- "Accurate psychic, psychic medium and clairvoyant readings are available today. Our extraordinary psychics, mediums and clairvoyants use their psychic ability to provide you with guidance in relationships, love, finances, and other life hurdles."
  • Decorative trinkets
    • Snow Globe Gifts -- "Snow Globe Gifts! Send your friends realistic, shakeable, snow globes..."
    • Christmas Music Tree -- "Create your own special Christmas Tree. Decorate your tree with your friends and make them play many famous Christmas songs. It's your Musical Christmas Tree."
    • My Fab Bag -- "Buy and give your friends designer handbags. Choose your favorite to carry and display on your profile."
  • Finding a boyfriend
    • Likeness UNRATED -- "Find out who you're like on mature topics like purity, vices, and the seven deadly sins. Can you find a perfect match?"
    • Will you KISS me? -- "Send kisses to loved ones, lovers, romantics, mistresses and everyone! Ever wanted a friend or crush to kiss youand find that they want to kiss you too What if it happens on a Full moon night? Give and take kisses"
  • Just good ol' pestering people
    • Zombies -- "Bite your friends and make them zombies! Mmmmm... Brains! Also - you can fight Zombies, Vampires and Werewolves now!"
    • Vampires -- "From the makers of Zombies comes Vampires! Kind of like Zombies. Except that the vampires are hot. VERY hot. Also - you can fight Zombies, Vampires and Werewolves now!" [C]
    • X Me -- "Tired of just poking? X me opens up a whole new world of action-based messaging, for example 'Hug Her, Slap Him, Tickle Them!'"
Is this trash what I really want to spend my time developing? Do people actually waste their time using this filth? It's depressing that humans' frontal lobes have not yet developed sufficiently to resist soliciting the advice of fortune-teller applications. [D] Given this kind of crowd, I don't think I could expect anyone to take me seriously if I told him I was developing a Facebook application. I would anticipate him laughing in my face.

That's why I don't develop for the Facebook platform: it's pure hype. Nothing of significance has been produced in the form of a Facebook application, and the only applications that get any views are ones that are made by companies who specialize in them. This environment exists at the whim of Facebook and its investors, and could come crashing to a halt if the business goes belly-up or Mr. Zuckerberg has a change of heart. I'll take my code somewhere else, thank you very much.

===========================

[A] Prepare for some awful, awful music and graphics if you go to RockYou!'s page. I had the displeasure of being aurally assaulted by Lil' Mama blowing kisses at me. You have been warned.

[B] To hammer this point into the ground, RockYou!'s CEO discusses here how, in order to prepare for an expected spike in traffic, they ran around filling a 24-ft truck full of servers and hooking them up over a weekend. Does this sound like the kind of thing you could pull off with the change you found under the sofa? I didn't think so.

[C] "From the makers of Zombies..." As if Zombies was a fantastic, useful product to stake their reputation on. They have WereWolves, too. Maybe there's more, I didn't care to look.

[D] And there's a hell of a lot more dumb applications, if you want to take a peek.

[E] He expands on the "Facebook as AOL" theme in this post. Scott Rosenberg also has his thoughts on the subject.