锻造坊 - 社交 Google 小工具
过去一年,像 Facebook 这样的社交网站经历了爆炸式增长。人们抓住机会寻找现有朋友、结交新朋友,并在网上花时间交流和参与群体活动。Facebook 可能是最知名的网站,但 LinkedIn、Ning、Hi5、Orkut 和其他网站也变得很受欢迎。
正如我们可能在竞争激烈的市场中所预期的那样,这些网站中的每一个都试图提供独特的功能来鼓励新用户注册。在 2007 年夏天,Facebook 在其开发者平台中推出了一项最有趣和最强大的功能之一——基本上,这是一种将第三方 Web 应用程序集成到 Facebook 中的方法。
这个 API 导致了大量为 Facebook 开发的应用程序。目前尚不清楚是否有人通过这些应用程序赚钱,或者是否有任何应用程序是人们认为真正有用的(而不是无聊的)。但是,有很多迹象表明 Facebook 的 API 是社交网络应用程序和一般 Web 应用程序的一个重要里程碑。我们首次拥有一个为应用程序开发提供开放平台的网站。
为了回应 Facebook 开发者 API 的流行,许多竞争对手宣布他们将支持类似的 API,称为 OpenSocial。为 OpenSocial 编写的应用程序应该在所有兼容的社交网络上同样有效。因此,您可以编写一次应用程序并将其部署在许多不同的网络上,而不是为 MySpace 编写一个应用程序,再为 Ning 编写另一个应用程序。至少目前而言,Facebook 是个例外;Facebook 是否决定加入 OpenSocial 联盟或提供兼容层还有待观察。
OpenSocial 规范由 Google 牵头制定,并且基于称为 Google 小工具的规范,Google 小工具在个性化的 iGoogle 页面中已经存在一段时间了。上个月,我们了解了如何构建一个简单的 Google 小工具,该小工具将 HTML 和 JavaScript 打包到 XML 包装器中。
本月,我们将了解如何将我们简单的 Google 小工具变成一个符合 OpenSocial 标准的应用程序。我们开始了解 OpenSocial 标准的优点和缺点,并考虑如何利用其功能。
正如我们上个月看到的那样,最简单的“Hello, world”Google 小工具如下所示
<?xml version="1.0" encoding="UTF-8" ?> <Module> <ModulePrefs title="Hello world" /> <Content type="html"> <![CDATA[ Hello, world! ]]> </Content> </Module>
该小工具以 XML 文件形式提供,包含 Module 节和 Content 节。Module 节允许我们使用 ModulePrefs 标签指定特定于小工具的偏好设置。Content 节正如您可能期望的那样,包含将为用户显示和执行的 HTML 和 JavaScript。
我们可以通过在 Module 标签中添加一个新的 Require 标签,将一个简单的小工具变成一个 OpenSocial 小工具
<?xml version="1.0" encoding="UTF-8" ?> <Module> <ModulePrefs title="Hello world" /> <Require feature="opensocial-0.6" /> <Content type="html"> <![CDATA[ Hello, world! ]]> </Content> </Module>
Require 标签表明我们的小工具正在实现 OpenSocial 标准的 0.6 版本。(毫无疑问,当本专栏印刷时,新版本将会发布。初始版本 0.5 已于 2007 年 12 月下旬被 0.6 版本取代。)除了这一行代码之外,这与我们上个月在 iGoogle 页面上安装的“Hello, world”小部件相同。从理论上讲,我们可以继续在我们选择的社交网站(OpenSocial 容器)上安装此应用程序,它将正常工作。
“Hello, world”作为一个独立的程序已经够无聊了;将其用作社交网络 API 的示例似乎几乎是愚蠢的。为了使小工具成为一个完全成熟的 OpenSocial 应用程序,它需要展示与其他人互动的能力。更准确地说,一个具有社交意识的应用程序应该能够了解我和我的朋友的一些信息,以及我(和我的朋友)做什么。
OpenSocial API 通过提供三种类型的功能来解决这个问题
人员和关系:获取关于您、您的朋友以及与这些朋友相关的各种数据的信息。Person 类提供对这些信息的访问。
活动:社交网站之所以有趣,是因为它们让您可以与朋友进行各种活动互动。这些活动范围可以从交换消息到回答在线投票中的问题,再到及时了解最新的体育比分。OpenSocial 将活动视为特定容器内的一系列操作。Activity 类提供对这些数据的访问。
持久性:OpenSocial 使应用程序可以在会话之间存储信息。此持久性 API 最有趣的方面之一是存储由 OpenSocial 容器而不是应用程序处理。没有 Persistence 类来处理此类数据。相反,数据是通过调用整体 opensocial 对象上的方法来读取和写入的。请注意,持久性层允许应用程序根据需要全局存储数据,以及按用户或按应用程序实例存储数据。
与这三个对象以及一般的 OpenSocial API 的交互是通过在 opensocial 对象上调用方法来完成的。通常,方法以异步方式执行,回调方法被指定为调用参数之一。例如,我们可以通过创建一个新的 OpenSocial 数据请求并指示我们想要提出的请求,来获取有关当前正在运行(查看)我们的应用程序的人的信息
var req = opensocial.newDataRequest(); req.add(req.newFetchPersonRequest(opensocial.DataRequest. ↪PersonId.VIEWER),"viewer");
然后我们将请求发送到我们的容器
req.send(response);
response 参数是一个函数;一旦请求返回响应,该函数将被调用。此外,当 response 函数被调用时,它将被传递一个包含我们方法调用结果的单个参数。
我们可以在单个数据请求对象中发送多个查询;我们所要做的就是多次调用 req.add。正如您从上面的代码行中看到的那样,调用 req.newFetchPersonRequest 需要我们既指示我们想要请求什么,又给它一个符号名称(viewer)。这种命名方式允许我们在单个对象中分离不同类型的响应数据。
您可能想知道是什么阻止了查看者从 OpenSocial 容器中检索任意数据。答案是 OpenSocial 定义了两种基本类型的人:查看者和所有者。正如我们所见,前者指的是正在运行和查看操作的人——如果我们的系统允许匿名浏览,甚至可能指根本没有人。相比之下,所有者必须是系统上已定义的人,并且很可能与查看者是同一个人。但至少在理论上,OpenSocial 将仅向查看者提供关于他们没有关系的所有者的有限信息。
也许我们可以用 OpenSocial 编写的最简单的应用程序类型之一是显示当前用户的朋友的应用程序。更好的是,由于社交网站上的朋友通常会上传他们的照片,我们甚至可以显示查看者的朋友列表。
上个月,我们了解了如何修改 Google 小工具(或 OpenSocial 应用程序)正在运行的 HTML。创建一个空的 div,在一个变量中构建 HTML,然后将 div 的 innerHTML 属性设置为该变量的属性。例如
html = "<p>Hello</p>"; div.innerHTML = html;
为了显示查看者的朋友列表,我们需要检索这些朋友的列表。然后我们可以迭代这些朋友,将他们的缩略图图像 URL 放入我们的 html 变量中。
为了检索朋友列表,我们必须执行以下操作
viewer_friends = opensocial.DataRequest.Group.VIEWER_FRIENDS; req.add(req.newFetchPeopleRequest(viewer_friends, opt_params), ↪"viewer_friends"); req.send(response);
上面的请求包含一个单独的查询,我们称之为 viewer_friends。(不要被 viewer_friends 变量混淆,引入该变量只是为了使代码行更容易理解。)
当方法异步执行完成后,它会调用我们的 response 函数。我们可以像定义任何其他 JavaScript 函数一样定义它,并且 Google 的文档甚至表明您可以在 OpenSocial 应用程序中使用 JavaScript 库,例如 Prototype 或 Dojo。
Google 已经将其实现的小工具中包含了一些有用的 JavaScript 函数,这意味着我们可以使用类似 Ruby 的 each 方法。该方法通常在数组上调用,它接受一个函数作为参数。该函数对于数组的每个元素执行一次,每个数组元素依次传递给该函数。因此,我们可以将我们的 response 方法编写如下
function response(data) { var viewer_friends = data.get("viewer_friends").getData(); viewer_friends.each(function(person) { var thumb = person.getField(opensocial.Person.Field.THUMBNAIL_URL); html += '<img src="' + thumb + '"/>'; }); document.getElementById('main').innerHTML = html; }
我们的 response 方法仅在请求发送后才被调用。它的 data 参数填充了我们查询的响应,我们可以使用其名称 (viewer_friends) 检索该响应。然后我们使用结果对象上的 getData() 方法来为我们提供我们感兴趣的数据,即 person 对象数组。
OpenSocial 中的每个人都有一些必需的属性,其中包括他们的个人缩略图图片的 URL。您可以从上面的示例中看到,我们通过在 person 上调用 getField() 方法来检索它,通过使用 OpenSocial 框架提供的值来指示我们想要的字段。我们可以使用几个这样的值,包括 ID(用于他们的唯一 ID)、NAME(用于他们的名字),甚至 PROFILE_URL(用于该人员在系统上的主页 URL)。除了这些基本字段之外,一个行为良好的 OpenSocial 应用程序必须查询其容器以确保它可用。
OpenSocial 最大的问题之一是其固有的多样性和跨平台功能。创建桌面应用程序的程序员已经发现——通常是通过痛苦的方式——不同的操作系统对于对话框甚至菜单的外观和感觉有不同的约定。这些通常很微妙的设计区别可能在应用程序的可用性中起着重要作用。
因此,看看当 OpenSocial 应用程序发布并应该在所有系统上干净利落地工作时会发生什么,这将很有趣。Facebook 平台的一大优势在于它将应用程序内容塞入标准的观感。OpenSocial 缺少这一点,尽管它鼓励多样性,但我远未确信这对最终用户有利。
OpenSocial 的另一个更严重的问题是,它旨在让应用程序在不同的上下文中运行,而不是无缝地连接来自不同社交网络系统的数据。是的,软件开发人员可以同时在多个平台上发布他们的代码,这很好。但作为用户和开发人员,我都有兴趣从我所属的所有社交网络中获得所有朋友/联系人/链接的完整列表。
就在我写下这些文字的几周前,著名博主 Robert Scoble 因为将他的联系人列表下载到另一个程序而被 Facebook 踢出。(他的帐户在几天内被恢复。)数据应该锁定在这些系统之一中,而不是由输入和批准它的人自由下载和传输,这种概念令人失望。
如果我使用 OpenSocial 创建一个论坛应用程序,并且我使用持久性 API 来存储消息,那么它可能工作得很好。但是,如果我希望论坛跨不同的网络工作,以便论坛帖子不仅在用户之间持久存在,而且在不同的 OpenSocial 容器之间也持久存在呢?这似乎完全不受标准支持。虽然这种能力似乎与各种社交网络公司的利益背道而驰,但它肯定符合个人用户的利益。
当然,鉴于 OpenSocial 只不过是一个规范和一组 JavaScript 库,仍然存在希望。也许有人会创建一个 JavaScript 库,该库允许 OpenSocial 客户端应用程序以可以在系统之间轻松解包和使用的格式在远程服务器(即,不在 OpenSocial 容器的服务器上)上存储和检索状态。这样的库可能很难创建,特别是考虑到各种用户可见性和隐私问题。但是,这将是朝着不仅代码可移植性,而且数据可移植性迈出的又一步,这是许多人希望在 OpenSocial 中看到的。
我应该注意到,我不是第一个或唯一一个提出这些担忧的人。蒂姆·奥莱利 (Tim O'Reilly) 等人对 OpenSocial 的初始版本表示失望(请参阅“资源”)。
OpenSocial 为适合社交网站的应用程序提供了一个标准库和打包系统。假设有足够多的网站实施 OpenSocial 规范,这将大大减轻开发人员的负担,他们仍然需要为 Facebook 开发应用程序。
本月,我们简要了解了 OpenSocial 标准为开发人员提供了什么,以及我们如何创建利用这些支持的应用程序。我们还了解了 OpenSocial 应用程序如何与封闭容器通信。最后,我们看到了我们甚至可以用几行精心挑选的代码创建一个简单的应用程序。
OpenSocial 是否会成功,无论是靠自身还是作为 Facebook 开发平台的竞争对手,仍有待观察。我确实认为它需要变得更加成熟才能真正有用。但是,意图绝对是积极的,并且这项标准很有可能带来好处。
资源
示例:code.google.com/apis/opensocial/articles/firstgadget/firstgadget-0.6.html
OpenSocial 描述:blog.pmarca.com/2007/10/open-social-a-n.html
OpenSocial 屏幕广播:blog.pmarca.com/2007/10/open-social-scr.html
OpenSocial 规范:code.google.com/apis/opensocial/docs/spec-0.6.html
蒂姆·奥莱利关于 OpenSocial 中“数据移动性”的论点:radar.oreilly.com/archives/2007/11/opensocial_social_mashups.html
Reuven M. Lerner 是一位长期的 Web/数据库开发人员和顾问,是西北大学学习科学专业的博士候选人,研究在线学习社区。在芝加哥地区生活四年后,他最近(与妻子和三个孩子)返回以色列莫迪因的家。