Recently I logged into Facebook and saw a notification on my news feed that someone who'd I'd met at Microsoft under professional circumstances had uploaded some pictures. I clicked on the link and saw what looked like a college prank. There was a picture of a person being led down a hall way while entirely nude by a member of the opposite sex while others watched nonchalantly. Another picture had multiple naked people of the same sex in the aforementioned hall way, one of them in a suggestive position. After those two pictures I'd seen enough and clicked away.

The problem here is the one I've blogged about previously in posts like Facebook's Achilles Heel: Handling Multiple Social Contexts and that Cory Doctorow recently wrote about in his article How Your Creepy Ex-Co-Workers Will Kill Facebook. The person who uploaded the photos [who happens to be a college student] didn't consider that although the pictures may have been fine to share with college buddies, they probably aren't OK to share with people who you've only met in a professional context. Facebook's poor handling of multiple social contexts (professional acquaintances vs. college buddies) caused an embarrassing situation for both of us. Cory Doctorow's article tells of a similar story which is excerpted below

Here's one of boyd's examples, a true story: a young woman, an elementary school teacher, joins Friendster after some of her Burning Man buddies send her an invite. All is well until her students sign up and notice that all the friends in her profile are sunburnt, drug-addled techno-pagans whose own profiles are adorned with digital photos of their painted genitals flapping over the Playa. The teacher inveigles her friends to clean up their profiles, and all is well again until her boss, the school principal, signs up to the service and demands to be added to her friends list. The fact that she doesn't like her boss doesn't really matter: in the social world of Friendster and its progeny, it's perfectly valid to demand to be "friended" in an explicit fashion that most of us left behind in the fourth grade. Now that her boss is on her friends list, our teacher-friend's buddies naturally assume that she is one of the tribe and begin to send her lascivious Friendster-grams, inviting her to all sorts of dirty funtimes.

Thus I was quite pleased to look at the list of upcoming Facebook features and notice the following item which indicates that similar occurrences will be mitigated in the future.

Sort out your friends.

We’ll let you organize that long list of friends into groups so you can decide more specifically who sees what.

Of course, the proof is in the pudding. Given that I have been disappointed by Facebook's recent attempts to fix flaws in their user experience such as the thumbs up, thumbs down in the News feed and Facebook Beacon 2.0, it isn't a given that the ability to Sort out your friends described above will reduce the number of awkward social situations that occur when one's different social contexts are forced to blend together due to the existence of a single, unified "friends" list.

Cory Doctorow seems to think it is inevitable that no one will get this right when he writes

It's not just Facebook and it's not just me. Every "social networking service" has had this problem and every user I've spoken to has been frustrated by it. I think that's why these services are so volatile: why we're so willing to flee from Friendster and into MySpace's loving arms; from MySpace to Facebook. It's socially awkward to refuse to add someone to your friends list -- but removing someone from your friend-list is practically a declaration of war. The least-awkward way to get back to a friends list with nothing but friends on it is to reboot: create a new identity on a new system and send out some invites (of course, chances are at least one of those invites will go to someone who'll groan and wonder why we're dumb enough to think that we're pals).

That's why I don't worry about Facebook taking over the net. As more users flock to it, the chances that the person who precipitates your exodus will find you increases. Once that happens, poof, away you go -- and Facebook joins SixDegrees, Friendster and their pals on the scrapheap of net.history.

I agree with the sentiment but disagree with the conclusion that seems to imply that no one is going to figure out how to get this right. I suspect Facebook will give it a good shot because the future of the company will eventually depend on it as the site's users grows older and have a longer history with the service. In the real world, we often reboot our social networks by switching jobs, graduating from school, getting married, etc. Unfortunately, social networking sites don't really account for that which leads to the jumping around that Cory describes.

If Facebook doesn't want its users to start "graduating" to the next hot social networking site as some users are doing by "graduating" from MySpace to Facebook, then they will have to figure out how to deal with multiple social contexts and people's need to reboot their social network as they experience life changes.


Categories: Social Software

November 30, 2007
@ 01:54 PM


November 30, 2007
@ 04:00 AM

I had some free time last night, so I ported my meme tracker in IronPython over to C# and integrated it into the RSS Bandit source tree. Below is a screenshot of the results of clicking the [Top Stories] button on my feeds today.

Screenshot of RSS Bandit 'Top Stories' Feature

Now the fun part of the code is over and the fit & finish begins. I probably need some CSS help to render that list in a style that is a little more pleasant and less utilitarian. I was going to start of by copying the TechMeme look and feel but any other suggestions are welcome.

After that I need to figure out what configuration options we should have, if any. Right now it shows the top 10 stories from the past week using a weighted scoring mechanism that rewards newly popular items and penalizes older ones. So a page with 3 links from your subscriptions today will rank higher than an item with 5 links from your subscriptions from three days ago. I’m not sure if people will want to change any of those factors (number of posts shown, the date range or the weighted scoring system) but then again I hate cluttering the UI up with configuration options that only 1% of our user base will ever use.

I should also decide if we show multiple posts from the same feed which link to the same item or just pick the newest one. Right now, I’m only showing a single post from the feed because I subscribe to planet feeds like MSDN Blogs and ASP.NET Weblogs which means that when there are announcements like the rebranding of Silverlight 1.1 to Silverlight 2.0 there are like 20 posts from those two feeds alone about it.

Finally, I was wondering about a “mark all items that reference this link as read” feature. For example, I really don’t need to read every post about Google’s clean energy aspirations or a geek dinner starring Robert Scoble and Dave Winer to get the gist of it. So being able to mark every post linking to these items as read once I read the main link would be nice. On the other hand, I am interested in all of the various opinions on Facebook Beacon from my subscriptions. So that rules out an automatic ‘mark as read’ feature which was my initial thought.  

Maybe I was wrong, there is still some fun coding left. Namaste.

Now playing: Dream - Shawty Is A 10 (remix) (feat. R. Kelly)


Categories: RSS Bandit

November 27, 2007
@ 04:00 AM

Recently I’ve read a number of negative posts about the Facebook Beacon which highlight how easy it is for a company to completely misjudge the privacy implications and ramifications of certain features in social software applications.

Charlene Li, a Principal Analyst at Forrester Research who specializing in social software trends and marketing, writes in her blog post Close encounter with Facebook Beacon  

I put a lot of trust in sites like Facebook to do the right thing when it comes to privacy. After all, the only stuff that gets out into the public is the stuff that I actually put in. Until now.

Earlier this week, I bought a coffee table on When I next logged into Facebook and saw this at the top of my newsfeed:

I was pretty surprised to see this, because I received no notification while I was on that they had the Facebook Beacon installed on the site. If they had, I would have turned it off.

I used my personal email address to buy the coffee table, so I was puzzled why and how this "personal" activity was being associated with my "public" Facebook profile.

David Treadwell, a corporate vice president of Windows Live, writes in his blog post entitled Blockbuster, you're fired

Yesterday evening, I decided to add a few movies to my Blockbuster queue. Upon adding movies, I was surprised to see toasts from Facebook showing up on the Blockbuster site indicating that something was being added to my Facebook news feed. When I finished adding movies, I went to Facebook to see what was going on. I was then quite surprised to learn that Blockbuster and Facebook were conspiring to broadcast my movie selections to my Facebook friends.

I am not normally uptight about privacy issues, but you guys really crossed the line on this one:

  • I had never told either Blockbuster or Facebook that you should share my movie selections with friends.
  • Neither of you asked me if you could take this action. You just went ahead and did it, assuming that I would not mind.
  • This sharing of information about me without my informed consent about the mechanism of sharing is absolutely unacceptable to me.

You can find similar complaints all over the Web from similarly Web savvy folks who you typically don’t see griping about privacy issues. In all of the complaints raised, the underlying theme is that Facebook violated the principle of putting the user in control of their user experience.

As someone who works on a competing service I have to give the folks on Facebook credit for shipping the Facebook Beacon so quickly. I assumed something like that was still about six months away from being on their radar. I do give them poor marks when it comes to how this feature has been rolled out. There are several problems with how this feature has been rolled out when it comes to how it affects their users.

  1. Linking identities and data sharing without user permission: One of the thinks people have found creepy about this feature is that they are automatically discovered to be Facebook users on sites that they have not told they use Facebook. In Charlene’s case, she actually uses different email addresses to log in on both sites which must have seemed even doubly weird to her at first. As Ethan Zuckerman points out in his post Facebook changes the norms for web purchasing and privacy this completely upturns user expectations of how privacy on the Web works especially when it comes to cookies.  

    It's a genuine concern that Facebook has opened a Pandora's box when you consider what could happen if it is deemed socially acceptable for Web sites to use cookies to actively identify users across sites as opposed to the passive way it is done today. I’m sure the folks at Google would be excited about this since thanks to AdSense and DoubleClick, they  probably have cookies on every computer on the Web that has cookies turned enabled in the Web browser. Today it’s Facebook, tomorrow Amazon and eBay are posting your purchase history to every OpenSocial enabled web site courtesy of the cookies from these sites or from Google ads on your machine.

  2. No global opt-out: There is no way to turn off this feature. The best you get is that when a site tries to publish an update to your news feed and mini-feed, you get an entry for the site added to your Privacy Settings for External Websites page on Facebook. I guess it never occured to Mark Zuckerburg and Justin Rosenstein that not sharing my purchase history with Facebook is a valid privacy option. Why do I have to police this list and refer back to it every couple of days to figure out if some new Web site is now publishing my private data to Facebook without my permission? 

    I expect that kind of myopia and hubris from the Googles and Microsofts of the world not Facebook. Wow, the honeymoon lasted shorter than I expected.

I suspect that Facebook will loathe fixing both issues. The first issue can’t really be solved by having partner sites provide an opt-in mechanism because there is the valid concern that (i) people won’t opt-in to the feature and (ii) the experience and messaging will vary too much from site to site for users to have a consistent set of expectations. This then points to Facebook having an opt-in page for partner sites that is part of the Facebook settings page for this feature but that may start getting away from the add 3 lines of code to reach millions of users sales pitch which they have going. Adding a global opt-out button is also similarly fraught with down side for Facebook.

At this point, they’ll have to do something. I’ll be impressed if they address both issues. Anything less is simply not good enough.

PS: The technically inclined folks in the audience should take a look at Jay Goldman’s excellent Deconstruction of the Facebook Beacon Javascript. Found via Sam Ruby.

Now playing: Eightball & MJG - Relax & Take Notes (feat. Project Pat & Notorious B.I.G.)


November 26, 2007
@ 01:56 PM

My weekend project was to read Dive Into Python and learn enough Python to be able to port Sam Ruby's meme tracker (source code) from CPython to Iron Python. Sam's meme tracker, shows the most popular links from the past week from the blogs in his RSS subscriptions. A nice wrinkle Sam added to his code is that more recent posts are weighted higher than older posts. So a newly hot item with 3 or 4 links posted yesterday ends up ranking higher than an item with 6 to 10 posts about it from five days ago. Using that sort of weighting probably wouldn't have occurred to me if I just hacked the feature on my own, so I'm glad I spent the time learning Sam's code.

There are a few differences between Sam's code and mine, the most significant being that I support two modes; showing the most popular items from all unread posts and showing the most popular items from the past week. The other differences mainly have to do with the input types (Atom entries vs. RSS feeds) and using .NET Libraries like System.Xml and System.IO instead of CPython libraries like libxml2 and blob. You can see the difference between both approaches for determining top stories on my feed subscriptions below

Top Stories in the Past Week

  1. Mobile Web: So Close Yet So Far (score: 1.71595943656)
  2. The Secret Strategies Behind Many "Viral" Videos (score: 1.52423410473)
  3. Live Documents is Powerful Stuff (score: 1.35218082421)

Top Stories in all Unread Posts

  1. OpenSocial (score: 5.0)
  2. The Future of Reading (score: 3.0)
  3. MySpace (score: 3.0) [Ed Note: Mostly related to OpenSocial]

As you can probably tell, the weighted scoring isn't used when determining top stories in all unread posts. I did this to ensure that the results didn't end up being to similar for both approaches. This functionality is definitely going to make its way into RSS Bandit now that I've figured out the basic details on how it should work. As much as I'd like to keep this code in Iron Python, I'll probably port it to C# when integrating it for a number of practical reasons including maintainability (Torsten shouldn't have to learn Python as well), performance and better integration into our application.

Working with Python was a joy. I especially loved programming with a REPL. If I had a question about what some code does, it's pretty easy to write a few one or two liners to figure it out. Contrast this with  using Web searches, trawling through MSDN documentation or creating a full blown program just to test the out some ideas when using C# and Visual Studio. I felt a lot more productive even though all I was using was Emacs and a DOS prompt. 

I expected the hardest part of my project to be getting my wife to tolerate me spending most of the weekend hacking code. That turned out not to be a problem because it didn't take as long as I expected and for the most part we did spend the time together (me on the laptop, her reading The Other Boleyn Girl, both of us on the sofa). 

There are at least two things that need some fine tuning. The first is that I get the title of the link from the text of the links used to describe it and that doesn't lead to very useful link text in over half of the cases. After generating the page, there may need to be a step that goes out to the HTML pages and extracts their title elements for use as link text. The second problem is that popular sites like Facebook and Twitter tend to show up every once in a while in the list just because people talk about them so much. This seems to happen less than I expected however, so this may not be a problem in reality.

Now I just have to worry about whether to call the button [Show Popular Stories] or [Show Most Linked Stories]. Thoughts?

import time, sys, re, System, System.IO, System.Globalization
from System import *
from System.IO import *
from System.Globalization import DateTimeStyles
import clr
from System.Xml import *

# USAGE: ipy <directory-of-rss-feeds> <mode>
# mode = 0 show most popular links in unread items
# mode = 1 show most popular links from items from the past week

all_links = {}
one_week =  TimeSpan(7,0,0,0)

cache_location = r"C:\Documents and Settings\dareo\Local Settings\Application Data\RssBandit\Cache"
href_regex     = r"<a[\s]+[^>]*?href[\s]?=[\s\"\']+(.*?)[\"\']+.*?>([^<]+|.*?)?<\/a>"
regex          = re.compile(href_regex)

(popular_in_unread, popular_in_past_week) = range(2)
mode = popular_in_past_week

class RssItem:
    """Represents an RSS item"""
    def __init__(self, permalink, title, date, read, outgoing_links):
        self.outgoing_links = outgoing_links
        self.permalink      = permalink
        self.title          = title           = date           = read

def MakeRssItem(itemnode):
    link_node  = itemnode.SelectSingleNode("link")
    permalink  = link_node and link_node.InnerText or ''
    title_node = itemnode.SelectSingleNode("title")
    title      = link_node and title_node.InnerText or ''
    date_node  = itemnode.SelectSingleNode("pubDate")
    date       = date_node and DateTime.Parse(date_node.InnerText, None, DateTimeStyles.AdjustToUniversal) or DateTime.Now 
    read_node  = itemnode.SelectSingleNode("//@*[local-name() = 'read']")
    read       = read_node and int(read_node.Value) or 0
    desc_node  = itemnode.SelectSingleNode("description")
    # obtain href value and link text pairs
    outgoing   = desc_node and regex.findall(desc_node.InnerText) or []
    outgoing_links = {}
    #ensure we only collect unique href values from entry by replacing list returned by regex with dictionary
    if len(outgoing) > 0:
        for url, linktext in outgoing:
            outgoing_links[url] = linktext
    return RssItem(permalink, title, date, read, outgoing_links)   

if __name__ == "__main__":
    if len(sys.argv) > 1: #get directory of RSS feeds
        cache_location = sys.argv[1]
    if len(sys.argv) > 2: # mode = 0 means use only unread items, mode = 1 means use all items from past week
        mode           = int(argv[2]) and popular_in_past_week or popular_in_unread

    print "Processing items from %s seeking items that are %s" % (cache_location,
                                                                  mode and "popular in items from the past week"
                                                                  or "popular in unread items" )
    #decide what filter function to use depending on mode
    filterFunc = mode and (lambda x : (DateTime.Now - < one_week) or (lambda x : == 0)
    #in mode = 0 each entry linking to an item counts as a vote, in mode = 1 value of vote depends on item age
    voteFunc   = mode and (lambda x: 1.0 - (DateTime.Now.Ticks - * 1.0 / one_week.Ticks) or (lambda x: 1.0)

    di = DirectoryInfo(cache_location)
    for fi in di.GetFiles("*.xml"):     
        doc = XmlDocument()
        doc.Load(Path.Combine(cache_location, fi.Name))
        # for each item in feed       
        #  1. Get permalink, title, read status and date
        #  2. Get list of outgoing links + link title pairs
        #  3. Convert above to RssItem object
        items = [ MakeRssItem(node) for node in doc.SelectNodes("//item")]
        feedTitle = doc.SelectSingleNode("/rss/channel/title").InnerText
        # apply filter to pick candidate items, then calculate vote for each outgoing url
        for item in filter(filterFunc, items):
            vote = (voteFunc(item), item, feedTitle)
            #add a vote for each of the URLs
            for url in item.outgoing_links.Keys:
                if all_links.get(url) == None:
                    all_links[url] = []

       # tally the votes, only 1 vote counts per feed
    weighted_links = []
    for link, votes in all_links.items():
        site = {}
        for weight, item, feedTitle in votes:               
            site[feedTitle] = min(site.get(feedTitle,1), weight)
        weighted_links.append((sum(site.values()), link))

    # output the results, choose link text from first item we saw story linked from
    print "<ol>"   
    for weight, link in weighted_links[:10]:
        link_text = (all_links.get(link)[0])[1].outgoing_links.get(link)
        print "<li><a href='%s'>%s</a> (%s)" % (link, link_text, weight)
        print "<p>Seen on:"
        print "<ul>"
        for weight, item, feedTitle in all_links.get(link):
            print "<li>%s: <a href='%s'>%s</a></li>" % (feedTitle, item.permalink, item.title)
        print "</ul></p></li>" 
    print "</ol>"


Categories: Programming

I've been reading Dive Into Python for a couple of days have gotten far enough to tell what the following block of code does if the object variable is an arbitrary Python object

methodList = [method for method in dir(object) if callable(getattr(object, method))]
    processFunc = collapse and (lambda s: " ".join(s.split())) or (lambda s: s)
    print "\n".join(["%s %s" %
                       processFunc(str(getattr(object, method).__doc__)))
                     for method in methodList])

However I've been having a tougher time than I expected with learning Python using Dive Into Python for a couple of reasons, some to do with how the book is laid out and some to do with my choice of IronPython as my Python implementation of choice. The main problems I've been having are

  • IronPython doesn't have a number of standard libraries that are used in the book such as os, xml.dom, UserDict, sgmllib and so on. This means I can't construct or run a number of the more advanced samples in the book.
  • The book seems to dive into meaty topics before covering the basics. For example, introspection (aka reflection) and lambda functions (aka anonymous methods)  are covered in Chapter 4 while defining classes and importing modules is covered in Chapter 5. Similarly, a discussion on for loops seems to have been removed from the most recent version of the book and replaced with a discussion on list comprehensions which are definitely superior but more alien to the novice.
  • I tend to learn comparatively. Thus I would love to get a more direct mapping of constructs in C# to those in Python with  discussions on Python features that don't exist in C#. This is the tack I took with C# from a Java Developers perspective and it seems a lot of people found that useful.

For these reasons, I thought it would be useful to create a set of tutorials for myself that would address some of these issues I've been having. Then I wondered if other C# developers wouldn't find such an article or tutorial useful as well. Are there any C# developers out there that would actually be interested in this or am I an edge case?

PS: I wouldn't expect to get time to actually writing, editing and publishing such tutorials until the summer of next year at the earliest (which I expect should coincide with the availability of IronPython 2.0). 


Categories: Programming

I’ve been working on simplifying my life and improving on my mental state over the last year or so. I’m now at the stage where I think I’ve gotten into a decent routine with diet and excercise. My next step [now that the rigors of buying the house and planning the wedding are over] is to broaden my programming horizons by learning a radically different programming language from my comfort zone, Python and C# respectively, while not harming my personal life or work habits.

It turns out that I can add an hour or two to my day by (i) leaving home earlier and thus avoiding traffic (ii) reading blogs less (iii) unsubscribing from most of the Microsoft internal mailing lists I was on and (iv) scheduling meetings so they are clumped together instead of having three meetings with 30 minutes in between each one thus burning up an hour of my time mentally twiddling my thumbs and checking email. 

So far I’ve installed IronPython and python-mode. I’ve also started reading Dive into Python and have gotten as far as Chapter 3. I’d just like to thank folks like Mark Pilgrim, Jim Hugunin and Barry Warsaw who are gifting programmers with such wonderful resources. Right now I’m still trying to wrap my mind around Everything is An Object

Everything in Python is an object, and almost everything has attributes and methods.

This is so important that I'm going to repeat it in case you missed it the first few times: everything in Python is an object. Strings are objects. Lists are objects. Functions are objects. Even modules are objects.

All functions have a built-in attribute __doc__, which returns the doc string defined in the function's source code. The sys module is an object which has (among other things) an attribute called path. And so forth.

So far this is already an enjoyable experience for someone who has mostly been programming in Javascript (not object oriented, dynamic but weakly typed) and C# (statically typed, no REPL) for the past few years.

Once I’m done reading Dive into Python, my plan is to integrate Sam Ruby’s MeMeme 2.0 into RSS Bandit. That way even though I’ve stopped reading blogs regularly, I don’t end up finding out days later that Visual Studio 2008 and .NET Framework 3.5 were released because it wasn’t on TechMeme or programming.reddit.  

Optimizing your life by writing code is fun. I guess this is what they call life hacking. Wink

Now playing: The Clash - Rock The Casbah


Categories: Programming

Via Steve Vinoski's Answers for Sergey I stumbled upon Sergey Beryozkin's Questions for Steve which started of with the following question

1. Do you think client code generation is evil ? If yes, do you expect people to do manual programming on a large scale ?

The problem with the software industry [or should I say humanity?] is that we like to take absolutist positions because they are easier to defend or argue against than admitting that the world is full of shades of gray.

Starting with the first question, code generation isn't necessarily bad let alone evil. However there are lots of problems with how code generation is implemented by the major vendors that support the SOAP/WSDL/XSD/WS-* family of technologies. Steve does a good job of laying out the problems with these approaches.

The first problem Steve points out is that a lot of these SOAP toolkits have implement some form of location transparency which tries to hide as much as possible the differences between invoking a remote system and calling a method on a local object. This behavior even flies in the face of SOA since one of the four tenets of service orientation is that boundaries are explicit. Another problem is that the inflexible and rigid requirements of static typing systems runs counter to the distributed and flexible nature of the Web. I posted a practical example a few years ago in my post entitled Why You Should Avoid Using Enumerated Types in XML Web Services. In that example, I pointed out that if you have a SOAP Web Service  that returns an enumeration with the possible value {CDF, RSS10, RSS20} and in a future release modify that enumeration by adding a new syndication format {CDF, RSS10, RSS20, Atom} then even if you never return that syndication format to old clients written in .NET, these clients will still have to be recompiled because of the introduction of a new enumeration value. I find it pretty ridiculous that till today I have list of "people we need to call and tell to recompile their code whenever we change an enum value in any of our SOAP Web Services". Of course, some of this foolishness can be mitigated in a statically typed system using technologies like Java's dynamic class loading but that is really just an insecure workaround that tries to hide the fact that what you really need here is a dynamically typed system. 

The second question is really asking whether we want developers writing XML processing code by hand instead of having a code generator do this work. Even though I used to work on the XML team at Microsoft, I do agree that it is a valid concern that you shouldn't want to spend a lot of effort writing code for parsing and processing XML if that is not the core function of your application. Again, Steve Vinoski hits the nail on the head with the suggestion to use standard data formats and MIME types. For example, if I decide to use application/atom+xml MIME type for the data that is returned by my RESTful Web service then clients can choose from a vast array of libraries for processing Atom feeds [such as the Windows RSS platform, ROME, Mark Pilgrim's Universal Feed Parser, etc] without having to write a lot of XML parsing code. If you must provide your own custom formats then it is imperative to make sure that it is easy to consume these formats from any platform by using a consistent and simple data model for the data format. A number of popular Web service APIs like the Flickr API, and the Facebook platform have provided client libraries for their APIs, this should be considered the exception and not the rule. Even in their case, it is interesting to note that a large proportion of the client libraries for these services are not actually maintained or developed by the creators of the service. This highlights the value of utilizing simple data formats and straightforward protocols. That way it isn't actually a massive undertaking for client developers to build and share libraries that abstract away the XML processing code. Of course, all of this can be avoided by just using standard MIME types and data formats that are already supported on a wide array of platforms instead of reinventing the wheel.


Categories: XML Web Services

In a comment on my previous post, pwb states

"REST" still suffers mightily from no real guidance on how exactly to construct something REST-ful. A dissertation doesn't cut it.

I guess it depends on what is meant by "real guidance". I can argue that there is no real guidance on how to construct object oriented systems, distributed applications or high performance data storage systems. Whether you agree or disagree with any of those statements depends on how "official" or "canonical" one expects such guidance to be.

If you are interested in building RESTful Web services. Here are the top 3 ways I suggest one learn about building and designing a RESTful system. 

  1. Learn the Atom Publishing Protocol: The best way to figure out how to build a RESTFul Web service is to actually use a well designed one and none is a better example of what a RESTful Web service should be than the Atom Publishing Protocol. For extra credit, you should also read up on Google's GData protocol and come up with a list of pros and cons of the approaches they've taken to extending AtomPub.

  2. Read Joe Gregorio's "Restful Web" column on Joe Gregorio is one of the editors of RFC 5023 (the Atom Publishing protocol) and is currently employed at Google working to make GData even more Web friendly. He started a series of articles on on building and designing RESTFul Web services complete with code samples. The entire list of articles can be found here but if you don't have the time to read them all, I suggest starting with How to Create a REST Protocol which covers the four decisions you must make as part of the design process for your service 

    • What are the URIs? [Ed note - This is actually  "What are the resources?" ]
    • What's the format?
    • What methods are supported at each URI?
    • What status codes could be returned?

    If you have more time I suggest following that article up with Constructing or Traversing URIs? which contrasts client access models based on URI construction [where clients have baked into them knowledge of the URI structure of your service] or by URI traversal [where clients discover resources by following links either within the primary resources your service returns or via a service document that describes your service's end points]. Just because WSDL is a disaster doesn't mean that interface definition languages aren't useful or that they aren't needed in RESTful applications. Afterall even Atom has service documents

    And finally, because I don't believe you get to design a system without being familiar with what the code looks like and should do, I'd suggest reading Dispatching in a REST Protocol Application which walks through what the server side code for a particular RESTful service looks like. He even throws in some performance optimizations at the end.

    Of course, I know you're actually going to read all the articles in the series because you're a dutiful lil' Web head and not shortcut seeker. Right? :)

  3. Buy "RESTful Web Services" by Leonard Richardson, Sam Ruby, and David Heinemeier Hansson:  If you are the kind of person who prefers to have a book than learning from "a bunch of free articles on the Internet" then RESTful Web Services is for you. I haven't read the book but have seen it on the desks of more co-workers than I'd care to admit and each of them favorably recommended it.  Sam Ruby, Leonard Richardson and DHH know their stuff so you'll be learning at the feet of gurus. 

To me, this seems like an abundance of resources for learning about building RESTful Web services. Now I understand that there are some for whom until it shows up on MSDN, IBM Developer Works or in a Gartner Report it might as well not exist. To these people all I can say is that "It must be great to have all that free time now that you have outsourced your thinking and business critical analysis to someone else". :)  


Categories: XML Web Services

Recently someone asked in the comments to one of my posts why I seem to be down on the WS-* family of technologies (XSD, WSDL, SOAP, etc) when just a few years ago I worked on Microsoft’s implementations of some of these technologies and used to blog about them extensively.

I was composing a response when I stumbled on James Snell’s notes on the recent QCon conference that captures the spirit of my “conversion” if you want to call it that. He wrote

Those who are familiar with my history with IBM should know that I was once a *major* proponent of the WS-* approach. I was one of the original members of the IBM Emerging Technologies Toolkit team, I wrote so many articles on the subject during my first year with IBM that I was able to pay a down payment on my house without touching a dime of savings or regular paycheck, and I was involved in most of the internal efforts to design and prototype nearly all of the WS-* specifications. However, over the last two years I haven’t written a single line of code that has anything to do with WS-*. The reason for this change is simple: when I was working on WS-*, I never once worked on an application that solved a real business need. Everything I wrote back then were demos. Now that I’m working for IBM’s WebAhead group, building and supporting applications that are being used by tens of thousands of my fellow IBMers, I haven’t come across a single use case where WS-* would be a suitable fit. In contrast, during that same period of time, I’ve implemented no fewer than 10 Atom Publishing Protocol implementations, have helped a number of IBM products implement Atom and Atompub support, published thousands of Atom feeds within the firewall, etc. In every application we’re working on, there is an obvious need to apply the fundamental principles of the REST architectural style. The applications I build today are fundamentally based on HTTP, XML, Atom, JSON and XHTML.

My movement towards embracing building RESTful Web services from being a WS-* advocate is based on my experiences as someone who worked on the fundamental building blocks of these technologies and then as someone who became a user of these technologies when I moved to MSN Windows Live. The seeds were probably sown when I found myself writing code to convert Microsoft’s GetTopDownloads Web service to an RSS feed because the SOAP Web service was more complicated to deal with and less useful than an RSS feed. Later on I realized that RSS was the quintessential RESTful Web service and just asking people “How many RSS feeds does Microsoft produce?” versus how many SOAP endpoints does Microsoft expose is illuminating in itself.

Since then we’ve reached a world where thousands of applications being utilized by millions of end users are built on RESTful Web services on the public internet. My favorite example of the moment is the Facebook developer platform and before that it was Flickr and Amazon S3. Compare that with the number of SOAP and WS-* interfaces that are being used to build real developer platforms that benefit end users on the Web today.

Earlier today, I was contemplating Don Box’s recent post where he complained about the diversity of authentication schemes of various RESTful Web services from the “J. Random Facebook/Flickr/GData” services on the Web today. Don seems to hint that WS-Security/WS-Trust would somehow solve this problem which is rightfully debunked by Sam Ruby who points out that all those technologies do is give you a more complicated version of the extensible authentication story that is available in HTTP. So the only real issue here is that there are actually enough RESTful Web services on the Internet for Don Box to complain about the diversity that comes from having a flexible authentication model for Web services. On the other hand, there are so few useful public WS-* Web services on the Web (read: zero) that Don Box hadn’t encountered the same problem with WS-Security/WS-Trust since no one is actually using them.

At this point I realize I’m flogging a dead horse. The folks I know from across the industry who have to build large scale Web services on the Web today at Google, Yahoo!, Facebook, Windows Live, Amazon, etc are using RESTful Web services. The only times I encounter someone with good things to say about WS-* is if it is their job to pimp these technologies or they have already “invested” in WS-* and want to defend that investment.

At the end of the day, my job is to enable successful developer platforms that enrich our users’ lives not pimp a particular technology. So if you are one of my readers and were wondering what was behind my shift from thinking that WS-* related technologies were the cat’s pajamas and my current RESTful Web services/APP/GData/Web3S bent, now you know.


Now playing: Brooke Valentine - Girlfight (feat. Big Boi & Lil Jon)


Categories: XML Web Services

November 14, 2007
@ 01:57 PM

I’ve finally gotten around to uploading a couple of pictures from our wedding day in Las Vegas.  Below are a few of the pictures I liked the most. Click on them to see more pics.

Wedding Favors

Guess Where?

Bride, Maid of Honor and Mom

Groom, Best Man and the Non-Conformist

It was a really nice day

Holding hands

The photographers took several hundred pictures and we’ve sifted through less than half of them. Since it’s taken us so long just to pick out this two dozen or so pictures I though if we waited much longer I’d be posting the wedding pics on around our first or second anniversary. Smile

Now playing: Jay-Z - What More Can I Say


Categories: Personal

Although the choice of whether to pick between WS-* and REST when deciding to build services on the Web seems like a foregone conclusion, there seems to be one or two arguments on the WS-* that refuse to die. You can find a them in the notes on the talk by Sanjiva Weerawarana at QCon, WS-* vs. REST: Mashing up the Truth from Facts, Myths and Lies 

  • history: why were WS created? people were doing XML over HTTP in 1998/1999
  • everyone invented their own way to do security, reliability, transactions, … (e.g. RosettaNet, ebXML)
  • Biggest criticism of SOAP in 2000: lack of security
  • REST-* is on its way - ARGH!

Today you can find other members of the Web Services community echoing some of Sanjiva’s points. You have Don Box in his blog post entitled Yes Steve, I've Tried saying

I wouldn't call myself an advocate for any specific technology (ducks), but I've spent a lot of time doing HTTP stuff, including a recent tour of duty to help out on our .NET 3.5 support for REST in WCF.

I have to say that the authentication story blows chunks.

Having to hand-roll yet another “negotiate session key/sign URL” library for J. Random Facebook/Flickr/GData clone doesn't scale. 

and even Sam Ruby adds his voice in agreement with his post  Out of the Frying Pan where he writes

I’d suggest that the root problem here has nothing to to with HTTP or SOAP, but rather that the owners and operators of properties such as Facebook, Flickr, and GData have vested interests that need to be considered.

For once I have to agree with Sanjiva and disagree with Sam and Don. The folks at Google, Yahoo!  and a bunch of the other Silicon Valley startups realize that having umpteen different application interfaces, authentication and authorization stories is a pain for developers build mashups, widgets and full blown Web applications. The answer isn’t as Don argues that we all jump on WS-* or as Sam suggests that Web companies have a vested interest keeping the situation fragmented so we have to live with it.

In fact, we are already on the road to REST-* as a way to address this problem. What happens when you put together AtomPub/GData, OpenID, OAuth and OpenSocial? Sounds a lot like the same sort of vision Microsoft was pitching earlier in the decade, except this time it is built on a sturdier foundation [not crap like SOAP, WSDL and XSD] and is being worked on collaboratively by members of the Web community instead of a bunch of middleware vendors.

It’s unsurprising that Don and Sam don’t realize this is occuring given that their employers (Microsoft and IBM respectively) are out of the loop on most of this evolution which is primarily being by driven by Google and it’s coalition of the willing. Then again, it does remind me of how IBM and Microsoft pulled the same thing on the industry with WS-*. I guess turnabout is fair play. Wink

Now playing: D12 - American Psycho


I've been pondering the implications of Facebook's SocialAds announcement and it has created some interesting lines of thought. The moment the pin dropped was when Dave Winer linked to one of his old posts that contains the following money quote

that's when the whole idea of advertising will go poof, will disappear. If it's perfectly targeted, it isn't advertising, it's information. Information is welcome, advertising is offensive.

If you think about it, the reason Google makes so much money from search advertising is because the ads are particularly relevant when a user is seeking information or a trusted opinion as part of the process to make a commercial decision. If I'm searching for "iPod" or "car insurance" then it is quite likely that ads selling me these products are relevant to my search and are actually considered to be information instead of intrusive advertising

Where Google's model breaks down is that a large amount of the advertising out there is intended to make you want to buy crap that you weren't even interested in until you saw the ads. In addition, trusted recommendations are a powerful way to convince customers to make purchases they were otherwise not considering. Former Amazon employee Greg Linden has written blog posts that indicate that 20% - 35% of Amazon's sales comes from recommendations like "people who like 50 Cent also like G-Unit". Given that Amazon made over 10 billion dollars in revenue last year (see financials), this means that $2 billion to $3.5 billion of that revenue is based on what Facebook is calling "social" ads.

So what does all this have to do with the title of my blog post? Glad you asked. Recently Yaron and I were chatting about the virtues of the Facebook platform. He argued that the fact that applications are encouraged to keep their data within their own silos (e.g. Flixster isn't supposed to be mucking with my iLike data and vice versa) prevents everyone [including Facebook] from benefiting from all this profile data being created from alternate sources. I argued that seeing the complexities introduced by having multiple applications being able to write to the same data store (e.g. the Windows registry) it's a lot better for users and app developers if they don't have to worry that some half baked app written by some drunken college kid is going to hose their Scrabulous scores or corrupt all their movie ratings. 

However what this means is that some of the juiciest data to serve "social" ads against within Facebook (i.e. movies and music) is not in Facebook's databases but in the databases of the developers of Facebook applications like Slide, iLike and Flixster. Considering the following entry that shows up in my friends news feeds after I performed an action in iLike ,

This entry could be improved with "social" ads in a way that is informative and valuable to my friends while also providing financial value to the application developer. For instance, would you consider the following changes to that entry to be advertising or information?

Flixster does an even worse job than iLike in making the actions they show in my news feed to be both useful and monetizable. Here's the kind of stuff that shows up in my news feed from Flixster

I don't know about you but I consider this spam. In fact, it is also misleading since what it really means is that someone on my friends list (Steve Gordon) has also installed the Flixster application on their profile. However what if the application actually published some of my movie ratings into the news feed with more context such as

People keep asking how Facebook application developers will make money. From where I'm sitting, this looks like a freaking gold mine. The problem seems to be that these applications either haven't yet figured out how lucrative a position they're in or are still in the audience acquisition phase until they flip to the highest bidder.

If Mark Zuckerburg has any strategic bone in his body, he'd snap up these companies before a hostile competitor like Google or Fox Interactive Media does. I'd put money on it that people are slowly realizing this all over Silicon Valley. 

What do you think?


When I first saw the Meebo Me widget, I thought it was one of the coolest things I’d ever seen on the Web. I immediately went to chat with some folks on our team and the response was that they were already way ahead of me. After a bunch of hard work, I’m glad to say that you can now embed the world’s most popular IM client into any Web page [including your blog or favorite social networking site] and let anyone who’s visiting that page chat with you while you’re online.

More details can be found in Casey’s post on the Windows Live Messenger team’s blog entitled Who wants IMs from the web? I do! I do! where she writes

The Windows Live™ Messenger IM Control lets people on the Web reach you in Messenger by showing your Messenger status on your web site, blog, or social networking profile. The Windows Live™ Messenger IM Control runs in the browser and lets site visitors message you without installing Messenger first. The IM Control is supported in IE6, IE7, and Firefox 2.0 on Windows and Firefox 2.0 on Mac OS. The IM Control is supported in 32 languages.

This is a nice addition to the IM button functionality announced in Ali's post.  An important difference between the two is that the new Windows Live™ Messenger IM Control allows people to send you IMs without installing Windows Live™ Messenger, and the IM button requires that they have it installed and are logged in.

I’ve already thrown it up on my Windows Live Space at so anyone who wants to chat with me in real time can holla at me without having to install any bits.  I expect it won’t be long before someone figures out how to port it to the Facebook platform which is something I’d love to see. I’d do it myself but I have RSS Bandit feature planning to work on in my free time. Smile

To prevent IM spam (aka SPIM), there is a Human Interactive Proof (HIP) challenge before a conversation can be initiated from the Web. For users concerned about privacy and wondering if anyone can just copy & paste some HTML, change some values and then spam you from the Web…rest assured this has been considered. In order for your online presence to be detected or IM conversations begun from the Web, you first have to turn on this feature. Safe defaults and making sure our users are always in control of their Web experience is key. 

So what are you waiting for? Come over and say hello.    

Now playing: Jodeci - Come & Talk To Me


Categories: Windows Live

Disclaimer: This post does not reflect the opinions, thoughts, strategies or future intentions of my employer. These are solely my personal opinions. If you are seeking official position statements from Microsoft, please go here.

Tim O'Reilly has an insightful post entitled OpenSocial: It's the data, stupid where he writes

My disappointment with OpenSocial was crystallized by an exchange between Patrick Chanezon, Google's developer advocate for the program, and an audience member at the OpenSocial session at Web 2.0 Expo Berlin.
Let's start with the first one. If all OpenSocial does is allow developers to port their applications more easily from one social network to another, that's a big win for the developer, as they get to shop their application to users of every participating social network. But it provides little incremental value to the user, the real target. We don't want to have the same application on multiple social networks. We want applications that can use data from multiple social networks.
Imagine what would have happened to Google maps if instead of supporting mashups, they had built a framework that allowed developers to create mapping applications across Microsoft, Yahoo! and Google as a way of competing with MapQuest. Boring! That's the equivalent of what they've announced here.

Given the amount of attention my last set of posts on this topic garnered I'm hesitant to write about OpenSocial again. I won't say much except to say that I'm glad to see that Tim O'Reilly gets it. At the end of the day, the most that can come from OpenSocial is that a bunch of sites are better able to create the kinds of walled gardens that Facebook has done. As an end user, this doesn't mean much to me since I'm already quite happy using my social networking site of choice.  It's pretty naive to think that the fact that some social networking site can now host Vampires or Scrabulous will make it a game changing competitor to Facebook. It shows a complete misunderstanding of the dynamics of social software.

The folks at Google trumpeted this announcement with the phrase "The Web is the Platform". I don't think that phrase means what they think it means. If you fight the Web, you will lose. I completely agree with Mark Cuban that the interesting thing is now that I've built so much metadata about myself, my interests and my relationships into Facebook, it would be great to utilize that investment around the Web. And I don't just mean showing me targeted ads for G-Unit sneakers  on Web sites I frequent because you know I friended 50 Cent.

C'mon Leah, you guys can do better than that. :)  


Categories: Social Software

I've seen a couple of recent articles talking about how Facebook has turned on it's platform developers with it's most recent announcements. Fortune magazine has an article today entitled Fear Among Facebook Developers which states

Zuckerberg wouldn’t deny it. On stage at the Web 2.0 conference in October in San Francisco, he acknowledged that his company reserves the right to build anything it wants and compete with any of its independent developers, but that the company intends to do this fairly. “We need to make sure we have the flexibility to do what we need as the platform grows—to be flexible enough able to add in the next big component [like the News Feed],” he said.

Yesterday Erick Schonfeld wrote an article on TechCrunch entitled iLike vs. Facebook: The Battle For The Music Artist that contains the following excerpt

Instead, Facebook is treating music artists just like any other brands, which can also set up their own Facebook pages, collect fans, and market to them directly. Yet, when it comes to music artists, one of Facebook’s most popular application developers, iLike, is doing the exact same thing.
So if you are a music artist, you now have to make a decision: Do you go with the iLike page as your main Facebook page (and take advantage of the nearly 10 million members who use the iLike app), or do you go with your own advertiser page on Facebook? Case in point: the new Facebook page for 50 Cent (shown left) had only three fans when it first went up just after midnight, compared to 1.2 million fans on his iLike page on Facebook.

This is a tale as old as the hills. Software platforms evolve and often this means incorporating features that were once considered as "features to be provided by others" as core parts of the platform. There are thousands of examples of application developers adding value to a platform that eventually became features of the platform due to popular demand. Whether it is adding a TCP/IP stack to the operating system, tabbed browsing to a Web browser or adding persistent searches to a Web mail application, it's all the same story. It is hard to argue that it isn't better for users such functionality to be a native part of the platform or underlying application, however it often leaves the platform developers in a lurch.

If the application developer cannot find a new way to add value to the platform then their usefulness to users comes to an end. This doesn't make it a slam dunk that once the platform vendor sees the value added by an application on it's platform, that things will eventually go sour for the application. There are many examples of vendors trying to compete with an application on their platform only to concede defeat and then try to acquire the company; PhotoBucket's acquisition by MySpace and Oracle's attempt to acquire BEA are two recent examples. [Editors note - I suspect that iLike vs. Facebook will end up going the same route as well]. In other cases, entry into the application space by the platform vendor helps to validate the market and draws more visibility to it from users.  

At the end of the day, articles like the ones I've mentioned above serve to prove that Facebook has actually built a viable and successful platform given that it is following the patterns of other successful platforms from the past several decades of the software industry.


Mitch Radcliffe has a blog post on ZDNet entitled Google: Does it have to be all FUD all the time? where he writes

Fear, uncertainty and doubt (FUD–see Wikipedia) is how IBM tried to retain its dominance, what Microsoft used to cement its monopoly and, now, I suggest we review recent Google news and wonder:
Basically, four of the last five press releases from Google have amounted to “me and my friends are going to…” beat a major competitor or rule a marketplace based on pre-announcements without a great deal of substance or products that can be seen and used today. Google sounds more like Microsoft circa 1988-to-1992, when it was launching consortia right and left to block competitors without delivering much, or any, real product. Microsoft still does this, but it doesn’t enjoy the credibility (or, better, the credulousness) that greet Google announcements.

It seems I'm not the only one that noticed this trend. I guess the Features Not Products initiative morphed into a "FUD Not Products" initiative somewhere along the line. :)

Or maybe they just hit a critical mass of ex-Microsoft employees from the old days.

PS: For bonus points, read Dave Winer's Why Google launched OpenSocial.


There's been a bunch of activity in the Windows Live world this week. The first bit of news is that a service I've been wanting us to ship for a while is now in public beta, Windows Live Calendar. You can learn more about it in the blog post titled Make some plans with the new Windows Live Calendar beta! on the Windows Live Hotmail team's blog which states

In the past few years, we’ve been investing heavily in building the best web e-mail offering. But part of the team has also been intently focused on delivering the next-generation web calendar: Windows Live Calendar. It’s been a long time coming and we’ve been pretty hush-hush about it. Today, we’re finally ready to invite the world to try the new Windows Live Calendar beta!

Stay coordinated with friends and family

If you have a family, you know how difficult it is to coordinate schedules between spouses and kids’ activities. If you’re a student, you know how consuming it is to find time to meet for school projects with your classmates. By sharing schedules on Windows Live Calendar, we take the chore out of coordination.

· Share as much or as little of your calendar with free/busy, read-only, or read/write permissions.

· Send friends a view-only secret link to your calendar so they don’t need to sign in with a Windows Live ID.

You can also make your calendar public, so if you’re running a business or an organization that is keen on promoting events, you can make it easy for people to find out what’s going on.

Get reminded

Sometimes we forget our commitments so Windows Live Calendar delivers you reminders through e-mail, Windows Live Messenger, or an SMS message on your mobile phone. You can also wake up to your upcoming schedule by including an RSS feed of your calendar on your favorite home page like, or Because Windows Live Calendar supports the iCal standard, you can add any ICS-based calendar you find on the Internet so you don’t miss out on your favorite sports games, movie openings or upcoming holidays. To start, try our holiday calendar list or go to the iCalShare site.

I've been using it quite a bit already and I have to say there's all sorts of AJAXy goodness in the product which is also described in the blog post. The bit in red font above is something I started of working with the Calendar team on until I switched projects and Ali took it over. Congratulations to the Calendar folks. I know they've been wanting to get this out for a while. Kudos on a great beta.

The next bit of Windows Live news is that you can now get a email address by going to or . The latter page informs readers

Here's the deal—if you currently have an e-mail address with or or a Microsoft Passport, you already have a Windows Live™ ID. Now you have a choice:

Keep your old account and continue to enjoy all of your favorite Windows Live services.


Get a new Windows Live ID (i.e., and take advantage of your fresh start!

The page goes on to explain how to switch email addresses but still keep all your information and contacts in Windows Live Hotmail and Windows Live Messenger. The always up to date folks at LiveSide have a comprehensive list of all the @live.xx domains that are available to choose from. So what are you waiting for? Get yours, I already got mine.

The final bit of news is that the next generation of Windows Live services and desktop products is finally here. All the Windows Live desktop applications and non-beta Web properties have been refreshed. You can learn more at or from the press release Microsoft’s Windows Live Free Online Services Available Now.

I personally like some of the favorable press this release has garnered in press such as Mary J Foley's article Microsoft’s Windows Live finally starting to come into its own which is excerpted below

Until recently, Microsoft has floundered badly when trying to explain exactly what Windows Live is and how Live services and Live software complement Windows. Last year, the Windows Live team was unveiling new services at a breakneck pace, but doing nothing to put them in context or explain when/how Microsoft planned to take them final.

Now Microsoft is starting to talk about different groupings of Windows Live services and software. It is positioning the Windows Live Client Suite as what users should install on their home PCs. is the starting point for users who want to “anywhere access” to their Windows Live services. is the home for Microsoft’s growing family of Live services for mobile phones and PDAs. For those with smartphones, another option is a client-style suite of Live services for mobile devices (like what Nokia is providing now on certain Windows Mobile phone models).

In the new Windows Live world order, the Windows Live taxonomy looks something like this:

Windows Live Client Suite (single installer and updater; client-based software with a services extension)

Windows Live Web Suite (service only)
Microsoft still has quite a way to go to make its Windows Live story truly intuitive and understandable by non-Microsoft-watchers. But compared to where the company was even a year ago, the Live team has come a long way.

Nice. That's a pretty big compliment coming from a skeptic like Mary J. :)

With all the releases, it's now time for my favorite part. Figuring out what we're going to ship next. Stay tuned.


Categories: Windows Live

I’ve started thinking about the next release of RSS Bandit and I thought it would be a good time to share some of my thoughts with our users and see what people would like us to add, fix or otherwise improve the application. It’s hard to believe that I started working on RSS Bandit almost five years ago. In that time, we’ve had the application downloaded over a million times and at the height of it’s popularity we were seeing up to a 100,000 downloads a month when we shipped a new release. Since then the popularity of the application has waned a little with the advent of Web-based feed readers like Bloglines and Google Reader as well as the fact that the amount of work Torsten and I can get done in our spare time pales in comparison to what folks who do this for a living like Nick Bradbury can get done.

That said, there are features I want from a feed reader that I don’t get from FeedDemon or Google Reader which is why I still work on RSS Bandit and why I started this blog entry. Below are the list of features I want us to do in the Phoenix release in order of which ones are most likely to be in the final version. Let me know what you think of them.

  • Meme Tracking: I’m now officially at the point where I don’t have enough time to read all the feeds I have in my subscription list anymore. For the most part, I’ve gotten around this by browsing programming.reddit, Techmeme and Sam Ruby’s MeMeme about once or twice a day. Although they are all great, the problem I have is that there are parts of the blogosphere that none of these sites is good at tracking. For example, none of these sites is really on top of the Microsoft employee blogosphere which I’m interested in for obvious reasons.

    I've been talking about building a feature similar to FeedDemon's popular topics for a long time but I've now gotten to the point where I don't think I can get a lot of value out of my blog subscriptions without having this feature.

  • Podcast Management User Interface: We kind of ran out of time with the last release and shipped a podcast downloading feature without an actual user interface for managing your podcasts (i.e. seeing pending downloads, percent complete, etc) which is really lame. Since I don’t subscribe to a lot of podcasts, this hasn’t been an issue. However I suspect that the reason I don’t is exactly because we didn’t complete implementation of this feature.

  • Plugin Model: One of the things I haven’t liked is that sometimes I want to add a single feature but once I check it in, I still need to wait for all the features slated for that release before we can get it out to users. We could move to having more frequent releases but I’m not sure people want to deal with reinstalling the application every two months because I added a single feature. What I’d like us to build a plugin model where we can ship meaningful extensions to the core application without having it tied to a release.

    I like the multi-pronged approach taken by Windows Live Writer where there are multiple APIs provided depending on the depth of integration and complexity of the functionality you’d like to add to the application. Torsten started on this a while ago but we never got around to refactoring the proposed extensibility APIs in a way that satisfied us.

  • Feeds Grouped by Sources: Right now, I’m not really happy with the way our integration with NewsGator Online works. There’s an issue with the fact that NewsGator doesn’t know what to do with intranet feeds or feeds that are actually on your local machine (for the wacky folks that subscribe to their system event logs). In addition, folks have asked if we'll ever integrate with the Windows RSS platform and I've had concerns about that since there are features we need that it doesn't provide.

    I’ve considered that the solution to both problems is to break out the My Feeds node into three sub-nodes; RSS Bandit feeds, Windows RSS platform feeds (shared with IE, Outlook and Windows Live Mail) and NewsGator feeds. This would require some radical re-engineering since it now assumes we’ll be using three different stacks to poll for feed updates but in the long run I think this is the right approach. This is probably the most complicated and controversial feature we’ll have in the release.  

  • A Single Node Mapping to Multiple Feeds: I was recently looking at my FriendFeed page and it brought home to me that many geeks have multiple feeds that represent the content they are placing on the Web. For example, my friend Joshua Allen has a personal weblog as well as a work-related weblog. It’s really lame to have two entries for him in RSS Bandit when it’s all the same person.

    The main problems with a feature like this aren't around the complexity of the information but more around how to represent this to users in the application in a way that is understandable and easy to manage.

If you are an RSS Bandit user I’d love to hear what you think of this list. Does this list sound relevant to you or are there more pressing features you’d like to see addressed first? Also what are your pet peeves?

PS: Someone recently asked me if there are any corporate RSS Bandit users. I know a bunch of folks use it at work and that some places actually have it as part of the default install on their work PCs but don’t have any details handy. If you have any anecdotes to share, I’d appreciate it.

Now playing: G-Unit - Poppin Them Thangs


Categories: RSS Bandit

November 6, 2007
@ 02:37 PM

Disclaimer: Although I work on the What’s New feed in Windows Live Spaces this should not be considered an announcement or precursor to an announcement of upcoming features of any Windows Live service.

Yesterday, I got into a debate with Yaron about whether Facebook has done enough to allow applications built on top of the Facebook platform to feel to end users as if they are part of a unified whole instead of merely being bolted on. I argued that they had, while Yaron felt otherwise.

The next time I logged into Facebook, I noticed the following which I hadn’t acknowledged up until that point. See if you can figure out the problem from the two screen shots. Mouse over for a hint.

See the Flixster Movies entry?

Where's Flixster?

The problem with building a platform on top of an existing application is that any problems users have with these platform applications ends up affecting their perception of your application in a negative way. How many people care that 70% of Windows crashes were caused by buggy device drivers that were for the most part written by hardware manufacturers and not part of Windows itself?

Recently I’ve seen a rush by some Web sites to jump on the platform bandwagon without clearly understanding how much work and how different a thought process it actually takes to get there. It will be an unfortunate shock for companies when they realize that it isn’t simply about chasing after feature sets. Building a platform is a holistic experience which includes getting the small details right, like giving users consistent opt out choices for the data they get in their news feed not just providing a bunch of APIs. Facebook is one of the few online services that gets it like 90% right and even they mess up on some things as I’ve pointed out above.

Think about that the next time someone shows you a bunch of APIs and tells you they’ve turned their Web site into a Web platform.

Now playing: G-Unit - I Wanna Get to Know You


Categories: Platforms | Social Software

A couple of people mentioned that my previous post on Google OpenSocial was too long and needed a five sentence elevator pitch style summary. Below is the five sentence summary of my analysis of Google OpenSocial that cuts through the hype and is just the facts.

OpenSocial is billed as a standardized widget platform for the Web, it isn't. OpenSocial is a standard set of REST APIs which social networks can utilize to expose user profiles and relationship data. Everything else required by a widget platform from authentication and authorization to user interface integration and an application directory is unspecified. OpenSocial is to a standardized widget platform as an internal combustion engine is to an airplane. A step in the right direction but still very far from the end goal.

Hope that helps. I have to go rake some leaves and run some puppy related errands so I might be slow in responding to comments over the rest of the day.


Disclaimer: This post does not reflect the opinions, thoughts, strategies or future intentions of my employer. These are solely my personal opinions. If you are seeking official position statements from Microsoft, please go here.

One of the Google folks working on OpenSocial sent me a message via Facebook asking what I thought about the technical details of the recent announcements. Since my day job is working on social networking platforms for Web properties at Microsoft and I'm deeply interested in RESTful protocols, this is something I definitely have some thoughts about. Below is what started off as a private message but ended up being long enough to be it's own blog post.

First Impressions

In reading the OpenSocial API documentation it seems clear that is intended to be the functional equivalent of the Facebook platform. Instead of the Facebook users and friends APIs, we get the OpenSocial People and Friends Data API. Instead of the Facebook feed API, we get the OpenSocial Activities API. Instead of the Facebook Data Store API, we get the OpenSocial Persistence Data API. Instead of FQL as a friendly alternative to the various REST APIs we get a JavaScript object model.  

In general, I personally prefer the Facebook platform to OpenSocial. This is due to three reasons

  • There is no alternative to the deep integration into the Web site's user experience that is facilitated with FBML.  
  • I prefer idiomatic XML to tunnelling data through Atom feeds in ways that [in my opinion] add unnecessary cruft.
  • The Facebook APIs encourage developers to build social and item relationship graphs within their application while the OpenSocial seems only concerned with developers stuffing data in key/value pairs.

The Javascript API

At first I assumed the OpenSocial JavaScript API would provide similar functionality to FBML given the large number of sound bites quoting Google employees stating that instead of "proprietary markup" you could use "standard JavaScript" to build OpenSocial applications. However it seems the JavaScript API is simply a wrapper on top of the various REST APIs. I'm sure there's some comment one could make questioning if REST APIs are so simple why do developers feel the need to hide them behind object models?

Given the varying features and user interface choices in social networking sites, it is unsurprising that there is no rich mechanism specified for adding entry points to the application into the container sites user interface. However it is surprising that no user interface hooks are specified at all. This is surprising given that there are some common metaphors in social networking sites (e.g. a profile page, a friends list, etc) which can be interacted with in a standard way.  It is also shocking that Google attacked Facebook's use of "proprietary markup" only to not even ship an equivalent feature.

The People and Friends Data API 

The People and Friends Data API is used to retrieve information about a user or the user's friends as an Atom feed. Each user is represented as an atom:entry which is a PersonKind (which should not be confused with an Atom person construct). It is expected that the URL structure for accessing people and friends feeds will be of the form  http://<domain>/feeds/people/<userid> and http://<domain>/feeds/people/<userid>/friends respectively.

Compare the following response to a request for a user's information using OpenSocial with the equivalent Facebook API call response.

<entry xmlns='' xmlns:georss='' xmlns:gd=''>
<title>Elizabeth Bennet</title>
<link rel='thumbnail' type='image/*' href=''/>
<link rel='alternate' type='text/html' href=''/>
<link rel='self' type='application/atom+xml' href=''/>
<gml:Point xmlns:gml=''>
<gml:pos>51.668674 -0.066235</gml:pos>
<gd:extendedProperty name='lang' value='en-US'/>

Below is the what the above information would look like if returned by Facebook's users.getInfo method


<users_getInfo_response xmlns="" xmlns:xsi="" xsi:schemaLocation="" list="true">
<city>Palo Alto</city>
<country>United States</country>

I've already mentioned that I prefer idiomatic XML to tunnelling data through Atom feeds. Comparing the readability of both examples should explain why.

The Activities Data API 

A number of social networking sites now provide a feature which enables users to see the recent activities of members of their social network in an activity stream. The Facebook news feed, Orkut's updates from your friends, and the Windows Live Spaces what's new page are all examples of this feature. The OpenSocial Activities Data API provides a mechanism for OpenSocial applications to access and update this activity stream as an Atom feed. All of the users activities or all activities from a specific application can be accessed using URIs of the form  http://<domain>/activities/feeds/activities/user/<userID> and http://<domain>/activities/feeds/activities/user/<userID>/source/<sourceID> respectively.  

Currently there is no reference documentation on this API. My assumption is that since Orkut is the only OpenSocial site that supports this feature, it is difficult to produce a spec that will work for other services without it being a verbatim description of Orkut's implementation.

There are some notes on how Orkut attempts to prevents applications from spamming a user's activity stream. For one, applications are only allowed to update the activity stream for their source directly instead of the activity stream for the user. I assume that Google applies some filter to the union of all the source specific activity streams before generating the user's activity feed to eliminate spam. Secondly, applications are monitored to see if they post too many messages to the activity stream or if they post promotional messages instead of the user's activities to the stream. All of this makes it seem difficult to see how one could specify the behavior of this API and feature set reliably for a diverse set of social networking sites.

The Persistence Data API 

The OpenSocial Persistence API allows applications to store and retrieve key<->value pairs that are either user-specific or are global to the application. An example of the former is a listing of company name and stock ticker pairs while an example of the latter is a user's stock portfolio. The feed of global key<->value pairs for an application can be accessed at a URL of the form http://<domain>/feeds/apps/<appID>/persistence/global for the entire feed and http://<domain>/feeds/apps/<appID>/persistence/global/<key> if seeking a particular key<->value pair. User-specific key<->value pairs are available at the URL of the form http://<domain>/feeds/apps/<appID>/persistence/<userID>/instance/<instanceID>.

This is probably the least interesting aspect of the API. A simple persistence API like this is useful for applications with simple storage needs that need to store user preferences or simple textual data that is needed by the application. However you aren't going to use this as the data storage platform for applications like iLike, Flixster or Scrabulous.

However I will add that an Atom feed seems like a horrible representation for a list of key<->value pairs. It's so bad that the documentation doesn't provide an example of such a feed.

Hosting OpenSocial Applications

The documentation on hosting OpenSocial applications implies that any site that can host Google gadgets can also host OpenSocial applications. In practice, it means that any site that you can place a <script> element on can point to a gadget and thus render it. Whether the application will actually work will depend on whether the hosting service has actually implemented the OpenSocial Service Provider Interface (SPI).

Unfortunately, the documentation on implementing the OpenSocial SPI is missing in action. From the Google site

To host OpenSocial apps, your website must support the SPI side of the OpenSocial APIs. Usually your SPI will connect to your own social network, so that an OpenSocial app added to your website automatically uses your site's data. However, it is possible to use data from another social network as well, should you prefer. Soon, we will provide a development kit with documentation and code to better support OpenSocial websites, along with a sample sandbox which implements the OpenSocial SPI using in-memory storage. The SPI implements:

  • Adding and removing friends
  • Adding and removing apps
  • Storing activities
  • Retrieving activity streams for self and friends
  • Storing and retrieving per-app and per-app-per-user data

The OpenSocial website development kit will include full SPI documentation. It will provide open source reference implementations for both client and server components.

I assume that the meat of the OpenSocial SPI is documentation is just more detailed rules about how to implement the REST APIs described above. The interesting bits will likely be the reference implementations of the API which will likely become the de facto standard implementations instead of encouraging dozens of buggy incompatible versions of the OpenSocial API to bloom.   


In general I believe that any effort to standardize the widget/gadget APIs exposed by various social networking sites and AJAX homepages (e.g. iGoogle, Netvibes,, etc) is a good thing. Niall Kennedy has an excellent series of articles on Web Widget formats and Web Widget update technologies that shows how diverse and disparate the technologies that developers have to learn and utilize when they want to build widgets for various sites. Given that Web widgets are now a known quantity, the time is ripe for some standardization.

That said, there are a number of things that give me cause to pause with regards to OpenSocial

  1. A common practice in the software industry today is to prefix "Open" to the name of your technology which automatically gives it an aura of goodness while attempting to paint competing technologies as being evil and "closed". Examples include OpenDocument, OpenID, OpenXML, OAuth, etc. In this case, OpenSocial is being positioned as an "open" alternative to the Facebook platform.  However as bloggers like Shelley Powers, Danny Ayers and Russell Beattie have pointed out, there isn't much "open" about OpenSocial. Russell Beattie asks in his post Where the hell is the Container API?

    Would people be jumping on this bandwagon so readily if it was Microsoft unilaterally coming up with an API, holding secret meetings geared towards undercutting the market leader, and then making sure that only those anointed partners get a head start on launch day by making sure a key part of the API isn't released - even in alpha. (It obviously exists already, all the partners have that spec and even sample code, I'm sure. The rest of us don't get access yet, until the GOOG says otherwise).

    Let's say we ignore that the process for creating the technology was not "open" nor have key aspects of the technology even been unveiled [which makes this more of a FUD announcement to take the wind out of Facebook's sails than an actual technology announcement], is the technology itself open? Shelley Powers points out her post Terms that

    Perhaps the world will read the terms of use of the API, and realize this is not an open API; this is a free API, owned and controlled by one company only: Google. Hopefully, the world will remember another time when Google offered a free API and then pulled it. Maybe the world will also take a deeper look and realize that the functionality is dependent on Google hosted technology, which has its own terms of service (including adding ads at the discretion of Google), and that building an OpenSocial application ties Google into your application, and Google into every social networking site that buys into the Dream.

    Google has announced a technology platform that is every bit as proprietary as Facebook's. The only difference is that they've cut deals with some companies to utilize their proprietary platform while Facebook's platform is only for use on the Facebook site. If Zuckerburg announces next week that the Facebook platform is freely implementable by any 3rd party Web site, where does that leave OpenSocial? After all, the Facebook platform is actually a proven, working system with complete documentation instead of the incomplete rush job that OpenSocial clearly is right now.

    There are all sorts of forums for proposing and discussing open Web technologies including the IETF, W3C, OASIS and even ECMA. Until all of the underlying technologies in OpenSocial have been handed over to one or more of these standards bodies, this is a case of the proprietary pot calling the proprietary kettle black.

  2. One of the things that comes along with OpenSocial is that Google has now proposed GData as the standard protocol for interacting with social graphs on the Web. This is something that I've been worried about for a while and I've written a couple of blog posts to address this topic because it is not clear that the Atom Publishing Protocol upon which GData is based works well outside it's original purpise of editing blog posts and the like. I'm not the only one that feels this way.

    Danny Ayers wrote in his post Open? Social?

    However the People Data API is cruel and unusual. It first stretches Atom until it creaks with "each entry in the People or Friends feed is a PersonKind"; then gives a further tug  (a person's name is represented using atom:title) then extends it even more (a person's email is gd:email) and finally mops up all the blood, sweat and dribble:

    Key value parameters - gd:extendedProperty - "As different social networks and other sources of People data have many different named fields, this provides a way for them to be passed on generally. Agreeing on common naming conventions is to be decided in future."

    Got to admire the attempt, but (to mix the metaphorical namespaces) silk purses don't make very good sow's ears either.

    In addition, AtomPub geek extraordinairre, Tim Bray wrote in his blog post entitled Web3S

    If you decide you totally can’t model your world as collections of entries populated with hyperlinks to express relationships, well then I guess APP’s not for you. And at the level of engineering intuition, I have to say that a monster online address book does feel different at a deep level from most online “publications” (I thought that was why we had LDAP... but I repeat myself).

    Now that we have AtomPub/GData as a de facto standard protocol for accessing various kinds of non-microcontent data on the Web as a reality, I'm done debating its suitability for the task since the horse has already left the barn. However I will continue to ask when will GData be RFC 5023 compliant?

  3. At the end of the day, the most disappointing thing about OpenSocial is that it doesn't really further the conversation about actual interoperability across social networking sites. If I use Orkut, I still need a MySpace account to interact with my friends on that site. Some people have claimed that OpenSocial will enable routing around such lock-in via applications like iLike and Flixster which have their own social networks and thus could build cross-site social networking services since they will be hosted on multiple social networking sites. However the tough part of this problem is how a hosted application knows that carnage4life@windowslivespaces is the same user as DareObasanjo@Facebook? It seems OpenSocial completely punts on satisfying this scenario even though it wouldn't be hard to add this as a requirement of the system. I guess the various applications can create their own user account systems and then do the cross-site social network bridging that way, which sucks because it will be a lot of duplicative work and will require users to create even more accounts with various services.

    Given that the big widget vendors like iLike, Slide and RockYou already have their users creating accounts on their sites that can be tied back to which social networking site the user utilizes their widgets on, this might be a moot point. Wouldn't it be mad cool if the Top Friends Facebook application could also show your top friends from MySpace or Orkut? I suspect the valuation of various widget companies will be revised upwards in the coming months.

  4. There is no mention of a user-centric application authorization model. Specifically, there is no discussion of how users grant and revoke permission to access their personal data to various OpenSocial applications. Regular readers of my blog are familiar with my mantra of putting the user in control which is why I've been so enthusiastic about OAuth. Although there is some mention of Google's Authentication for Web Application in the documentation, this seems specific to Google's implementation of OpenSocial hosting and it is unclear to me that we should expect that this is the same model that will be utilized by MySpace, Bebo, TypePad or any of the other social networking sites that have promised to implement OpenSocial. On the other hand, Facebook has a well thought out applications permission model and I would have thought it would be quite easy to simply reverse engineer that and add it to the OpenSocial spec than to simply punt on this problem.

Despite these misgivings, I think this is a step in the right direction. Web widget and social graph APIs need to be standardized across the Web.

PS: I've subscribed to the Google OpenSocial blog. So far there have only been posts by clueless marketing types but I'm sure interesting technical information that addresses some of the points above will be forthcoming.


November 3, 2007
@ 07:21 PM

I switched on my XBox 360 this morning only to be greeted by a green screen where the familiar XBox logo was supposed to be. In addition, it seems that I could get the sound fine but no picture. The only thing I can imagine that I did wrong was that I shut the console off while playing Marvel Ultimate Alliance instead of quiting the game before switching off the XBox 360 like I usually do.

Doing a search for "XBox 360 green screen" doesn't turn up anything particularly useful. Can anyone out there help with some suggestions on trouble shooting tips?

UPDATE: Disconnecting the XBox 360 from the power outlet for a few minutes then reconnecting it did th trick. Whew. :)


Categories: Video Games

In a post entitled Checkmate? MySpace, Bebo and SixApart To Join Google OpenSocial (confirmed) Mike Arrington writes

Google may have just come out of nowhere and checkmated Facebook in the social networking power struggle.

Update (12:30 PST): On a press call with Google now. This was embargoed for 5:30 pm PST but they’ve moved the time up to 12:30 PST (now). Press release will go out later this evening. My notes:

On the call, Google CEO Eric Schmidt said “we’ve been working with MySpace for more than a year in secret on this” (likely corresponding to their advertising deal announced a year ago).

MySpace says their new platform efforts will be entirely focused on OpenSocial.

The press release names, Friendster, hi5, Hyves, imeem, LinkedIn, Ning, Oracle, orkut, Plaxo,, Six Apart, Tianji, Viadeo, and XING as current OpenSocial partners.

We’re seeing a Flixster application on MySpace now through the OpenSocial APIs. Flixster says it took them less than a day to create this. I’ll add screen shots below.

Here’s the big question - Will Facebook now be forced to join OpenSocial? Google says they are talking to “everyone.” This is a major strategic decision for Facebook, and they may have little choice but to join this coalition.

Bebo has also joined OpenSocial.

I'm confused as to how Mike Arrington considers this a checkmate by Google. At the end of the day, this announcement is simply that folks like Slide and RockYou don't have to maintain multiple code bases for their widgets on various popular social networking sites. In addition, it brings the widget/gadget platform on these sites to a similar level to the Facebook platform. Of course, it won’t be on the same level unless it meets all the criteria from my post on how developers should evaluate the MySpace platform. Which is unlikely since besides MySpace, none of those sites have the userbase or engagement of Facebook users nor does any of them have the same kind of viral properties in distributing applications that Facebook platform has built-in

At the end of the day, will we see widget developers like the folks at iLike, Slide or Scrabulous leave the Facebook platform because of these announcements? Unlikely.

Will we see a mass migration from Facebook to MySpace or Orkut because you can now add Flixster or Scrabulous to your profile on these sites? Probably not.

So how is this a checkmate again?

OpenSocial simply keeps Facebook’s competitors in the game. It is more like a successful kingside castle than a checkmate.

Now playing: Backstreet Boys - Incomplete


In thinking about the Google OpenSocial Announcement I realized how much some of Google's recent moves remind me of Microsoft of old [for some undeclared definition of old]. We have

  • Google is now a two trick pony with two self reinforcing monopolies (Search + AdSense/Adwords) which is reminiscent of the self reinforcing nature of Microsoft's Windows + Office.

  • A scared overreaction to the growing hype of a startup that is eclipsing it in coolness. See OpenSocial reaction to Facebook

  • Several high level and very visible defections to said startup from people who were highly regarded there. Seems like just yesterday we were reading similar articles and blog posts about MSFT -> Google employee defections.

  • Said startup may be attacking Google's core monopoly in ways that were unforeseen but make sense in hindsight. See Facebook's SocialAds announcements.
  • Creation of de jure and de facto industry standards which are pitched as being great for customers but seem suspiciously like attempts at Fire & Motion. Compare WS-* to AtomPub + GData + OAuth + OpenSocial + ???.


James Snell has a blog post entitled Batch! which talks about the Batch processing model in GData APIs. He provides a sample of a GData batch request and points out the following

If the mere sight of this doesn’t give you shivers and shakes, let me give you a few reasons why it should:

  1. It’s not valid Atom. Note the first entry in the feed for instance. An Atom entry has an id, a title, some content, an author, some links, maybe some categories, etc. If the type of objects you want to represent does not also have those things, Atom is not the right format to use.
  2. It only works with Atom. What about binary resources like Jpeg’s? I guess we could base64 encode the binary data and stuff that into our invalid Atom entries but doing so would suck.
  3. We can’t use Etag’s and conditional requests
  4. I’m sure there are more reasons but these should be enough to convince you that a better approach is needed.

In a previous post I entitled One Protocol to Rule Them All and in the Darkness Bind Them I pointed out that since the Atom Publishing Protocol is not a good fit for interacting with data types that aren’t microcontent, it would need to be embraced and extended to satisfy those needs. In addition, this leads to problems because different vendors will embrace and extend it in different ways which fragments interoperability.

An alternative approach would be for vendors to utilize protocols that are better suited for the job instead of creating incompatible versions of a standard protocol. However the response I’ve seen from various people is that it is better if we have multiple slightly incompatible implementations of a single standard than multiple completely incompatible proprietary technologies. I’ve taken to calling this “the ODF vs. OOXML lesson”. This also explains why there was so much heat in the RSS vs. Atom debates but not so much when it came to debates over Yahoo’s podcasting extensions vs. Apple’s podcasting extensions to RSS.

Let’s say we now take it as a given that there will be multiple proprietary extensions to a standard protocol and this is preferable to the alternative, what should we have as the ground rules to ensure interoperability isn’t completely thrown out the windows? A fundamental ground rule should be that vendors should actually provide standards compliant implementations of the protocol before deciding to embrace and extend it. That way clients and services that conform to the standard can interoperate with them. In this regard, GData falls down horribly as James Snell points out.

Given that Joe Gregorio now works at Google and is a co-author of RFC 5023, I assume it is just a matter of time before Google fixes this brokenness. The only question is when?

PS: Defining support for batch operations in a standard way is going to be rather difficult primarily because of how to deal with failure modes. The fact that there is always the struggle between consistency and availability in distributed systems means that some folks will want a failure in any of the batched operations to result in the equivalent of a rollback while there are others that don’t care if one or two out of a batch of fifty operations fails. Then there are some folks in the middle for whom “it depends on the context” for which kind of failure mode they want.  

Now playing: Method Man - Say (feat. Lauryn Hill)