2006年8月23日星期三

HighRing - 成年人听不到的铃声

人听力的有效范围是20Hz~20KHz,而随着年龄所造成的听觉劳损,成年人会逐步丧失对高频声音的听觉。英国的一家企业由此原理开发出一种用于驱逐青少年的工具,通过播放14.4KHz的高频噪音让青少年远离一些不对青少年开放的商店。

然而当青少年明白其中的原理后,他们就想到了一种利用此原理且对自己有利的用法,那就是用高频声音作为手机铃声,也就是所谓的HighRing。HighRing最常见的使用方式就是用作上课时的铃声,学生本人能听到电话响了然后接听,而站在上面讲课的老师却听不到。

想下载HighRing的铃声,可以到HighRing.com这个网站,上面有5秒和15秒两种铃声,并且有wav和mp3版本。

2006年8月20日星期日

xFruits - 玩转RSS

既然说过要说一些大家都能看的东西,那从介绍一些大家都能用而且比较有趣的服务开始吧。今天推荐的是xFruits,一个专门提供RSS相关服务的网站,虽然6月就开始Beta了,不过知道的人应该不多吧。

在xFruits,你可以看到RSS聚合、RSS到网站、RSS到移动网站、贴子到RSS、RSS到PDF等各式转换服务。这些服务看似简单,但结合起来却很好用哦。例如你平时使用RSS阅读器订阅众多的Blog,希望也能在手机上直接浏览这些Blog却暂时找不到实现的方法,那么这时候你就可以先用RSS聚合功能将你订阅的Blog聚合为一个RSS,然后再用RSS到移动网站的转换生成一个适合在手机上看的页面,那就可以享受直接在手机上订阅众多Blog的效果了。

RSS到PDF也是一个不错的功能,例如你多年的个人发表堆积在MSN Spaces,虽然东西很多但是却散落在不同的类别里面,你想将这些东西整理为一本出版物,那就可以尝试RSS到PDF功能了。整理出来的PDF绝对会让你满意,它会帮你自动将每一篇文章按日期排下来,保持原本的图片和链接,同时还会自动按3种索引方式为你添加PDF书签:按日期、按标题和按来源。

2006年8月18日星期五

写大家都能看都能评论的东西?

长时间看着自己的Google Analytics报告,发现回头率极低,大多数人都是通过链接或搜索过来然后看完他要看的技术文章就走了,不回访也不订阅。

嗯……虽然我不是太在乎自己的blog被什么人阅读,不过我觉得养blog有点像养植物,这种方法不好养就换种方法,反正不容易死掉。现在考虑写一些能够让我身边的朋友看一看和评论的东西,因为一般评论过的人之后都会再回头看看其他人的新评论,希望这样能够增加回头率。

另外Title也准备改一下,"Cat's Life"这个名称是当初不明确要一个blog来干什么的情况下起的,现在我不同的blog应该根据内容来定制一些有意义的title。

Blog*Spot 解封 & 老牌 Blog 解说 & Blogger Beta

最近Blog*Spot可以直接从大陆访问了,不少人都开始转向用Blogger的服务,结果发现Blogger并没有现在常见的帖子分类/标签功能,而且模板编辑是纯HTML的也不容易上手。Blogger这么好声誉的网站服务就那么差吗?当然不是,这需要从blog的起源说起。

blog的始祖,或者说明是Blogger,开头考虑是给拥有个人网站的人用的。也就是我自己有一个个人网站,拥有静态的HTML,甚至是动态网站例如ASP/PHP。这时候我想写日志(当时还不明确叫做blog,或者刚刚开始叫做blog),那么我需要手动添加日志的页面,然后手动更新首页到各篇日志的链接,日志多了我会考虑每个月的日志都在一个页面集中起来或者集中链接,这叫做存档。但是手动这样做很不方便,就算空间支持动态我也懒得自己写数据库程序管理这一切,怎么办呢?这时候Blogger就来提供这部分服务了。

Blogger能够帮你保存日志的内容,然后自动帮你将内容生成HTML(考虑到多数空间仅支持静态HTML),然后通过FTP自动上传到你个人网站的空间(FTP上传是主流),这确实是一个很好的主意。发表的时候,你可以选择Blogger首页为blog.html,因为可能你自己的网站有真正的index.html,然后还有photos.html和books.html分别用于展示你的照片和阅读的书。那时候还没有flickr和douban,所以后面提到的两个频道是你自己手动更新的。

故事说完了,大家明白了吧?Blogger诞生的时代,面向的用户都是拥有自己的个人网站的,而Blogger只是用于自动生成网站其中的一部分,这些人都懂得如何编写HTML,所以他们一看就知道如何编辑HTML模板。至于后来完全为仅需要写blog的用户提供宿主服务的(也称作BSP),例如国内老BSP之一的blogbus.com,到现在的国内最多人用的MSN Spaces,都已经很傻瓜化。

顺便说一下的是,现在兼作宿主的BSP,提供存档功能仅仅是为了照顾大家的习惯。因为你看的根本就不是静态页面而是动态页面,动态筛选任何指定日期区间的帖子根本没难度也无差异。因此,这些BSP的存档一般都不允许你设置周期,就默认按月存档,不能好像Blogger那样按周或者日存档。

至于分类/标签是后来的BSP加上去的功能,Blogger这样的服务要实现分类的话它每次更新增量上传的数据量就要加大不少,如果你还经常修改分类/标签那么数据量就更加大了,这应该就是Blogger一直不肯增加分类这一功能的原因。不过最近Blogger提供的新的Blogger Beta服务开始支持这些功能,但Blogger Beta服务不能将blog以静态文件方式发布到你的FTP/SFTP,只能直接在Blog*Spot上展示。

2006年8月15日星期二

.NET 的灵魂是什么?

这是个很有趣的问题,但我觉得Microsoft也不能正面回答这个问题,估计他们会想rephrase这个问题,然后用他们的官方口吻回答。

先说说为什么会提这样的问题。那天和Piggest在逛购书中心,她说那些列很多Photoshop特效制作方法的书看再多都没有用,因为你看一个制作方法就只学到了这一个,而看《选择的艺术》这样的书,你才能领会到Photoshop的核心思想和使用方式,之后你就懂得如何灵活使用了。我接着就想,为什么ASP.NET的书都是那么肤浅,国内的书多数追求如何RAD式使用ASP.NET,国外的书就算在开发层面说得比较深入但都绝不提ASP.NET内部的一些运作机制,导致大部分ASP.NET的开发人员都只能按照一些官方给定的方式拼凑代码无法灵活发挥。为什么没有一本书能够抓得住ASP.NET的灵魂?是不是因为.NET本身就没有灵魂,所以你想抓也抓不到?

首先想一下MS会如何回答这个问题,.NET最有价值的地方就是语言无关。虽然它也好像Java那样应该是平台无关的,但是MS对非Windows平台的.NET Framework基本上毫无贡献,Mono发展至今也无法成为.NET Framework的第二选择。至于语言无关,这个特性的最大得益者似乎是MS而不是程序员,MS通过这招让大量其他语言的程序员转过来.NET。对于程序员来说,语言无关只是让不同语言的使用者能够方便的交流Assembly,但是对于设计与编码来说没有提供任何的核心思想。

接着MS应该会介绍.NET Framework自带的一大堆好好用的namespace,下面却是提供了很多很好用的类,例如ASP.NET 2.0就将Membership、Profile、WebPart等很实用的功能都引入了,大大方便了程序员。但是这又进一步突出了ASP.NET的RAD特性,除了RAD让人看不出它有任何深层次的思想。

那么除了提高开发效率,.NET有什么核心思想引导着所有的.NET开发人员,或许暂时没有。只有等MS慢慢成熟,整个企业塑造出一种除了赚钱和扩张以外的精神之后,.NET才可能有灵魂。

2006年8月14日星期一

第一次尝试使用 Windows Live Writer 发帖

今天在GFans看到有人提及Windows Live Writer,马上搜索一下是什么,结果发现是一个Blog工具,而且支持的API也不少,于是就下载了一个来玩玩。

安装的时候提示我是否需要装Windows Live Toolbar,犹豫了很久,最终决定装上,反正都是Beta,就试试看吧,虽然对Windows Live系列的Beta一向没有好感,结果发现原来是一个Google Toolbar的仿制品,T4拥有的功能它大部分都有,例如可以添加自定义按钮啊,可以自动填写表达啊,附加Virtual Earth, Live Mail, Live Spaces等我早就在Live Messenger看到厌烦的按钮。之后就很后悔选择了安装,马上通过IE的加载项管理把这些都禁用掉了。

然后说说装好的Windows Live Writer,填写Blog地址是发现出错,连接www.blogger.com/api总是被断开,不知道是哪方问题。之后发现它一个挺智能的地方,就是能够在你的Blog发一张临时贴,然后探测你的Blog的Style,那么你在编辑时就能够按照这种Style进行预览了。至于其功能,感觉一般半,就是界面漂亮,可以插入照片可惜我通常不直接上传照片而传到flickr,可以插入地图但遇到Virtual Earth的脚本错误。但总的来说MS现在的新产品都支持XHTML 1.0 Transition已经算是好事情,我开头也担心过它自动生成的是MS DOM那种糟糕的HTML。

暂时能说的就这么多了,试一下发表~

2006年8月10日星期四

Meebo 和 GMail + Talk 等 WebIM 的实现方式

我用Fiddler监听过Meebo和GMail + Talk,终于知道他们是如何实现event机制的了(也有人称之为Comet模式)。event包括好友发信息给你、好友上线/下线,甚至连是否显示某某人"is typing"的状态变换也算,反正就是指模仿桌面应用event机制需要服务器端主动触发客户端的东西。

例如有一个event.ashx是专门负责发送event消息的,那么工作的时候就保证一个客户端至少有一个活动的http连接在请求event.ashx。首先客户端要connect上去并发一个空的request请求event.ashx,然后服务器端则等待事件,如果在等待期间有事件发生则服务器端马上将事件信息写入response返回并disconnect掉,如果一段时间后没有事件发生则给出空的response并disconnect掉。客户端一旦收完response并被disconnect掉,马上进行下一次的connect和发送下一个空request以等待新的事件,如此重复下去。另外事件传输时可能也可以应用batch机制,也就是第一个事件触发后等几毫秒看看是否有紧随的事件,有的话也把其数据增加到response中一起发给客户端。

这样做的好处是,不会好像每秒一次请求检查事件那样非常消耗服务器端资源,但是占用着服务器的端口其实也是一种资源浪费。一台机65535个端口,幸运的话我想最多能够同时使用几百个,超过了网卡的缓冲区应该就负载不了了。

2006年8月8日星期二

中国IT从业人员学习障碍:心态大于语言

在查阅Atlas资料的时候我看到,竟然有人说用UpdatePanel不就已经很好,做出来的效果也无刷新,为什么还要花那么多时间去研究Atlas的客户端使用方式。这时候我想起Piggest关于中国CG界的评论,我才明白为什么中国的IT界总是和前沿技术扯不上关系,原来这不是语言造成的门槛,而是心态造成的障碍。为什么大家都不看英文的前沿资料呢?往往不一定是看不懂,而是不愿意使用前沿技术。使用前沿技术是有风险的,遇到致命问题将可能导致整个项目的失败,就算不至于项目失败项目也是在探索中前进的,项目的参与者必须一边研究一边之行执行项目,这是大多数单纯想赚钱的人不太愿意做的事情。 这就导致了大家都不愿意使用前沿技术,宁愿让别人把该技术用烂了自己才拿来用,因为用烂了的技术肯定是遍地资料的,别说"用",就算是"抄"也可以——随便搜索一下就可以把别人的成果拿过来。

同时这也造成一个恶性循环,就是在中国真正会去接触前沿技术的人也不会愿意和大家分享。如果你是常常看前沿技术文章的人,开头你会考虑将部分翻译为中文,或者用中文讲自己掌握到的资料表达出来,希望分享给中文社区的用户。但接着遇到的只会是其他人的忽略甚至是鄙视,你觉得你自己完全没必要对中文社区作贡献,这时候你就会下狠心不再管中文社区,反正你在英文社区也能和其他人很好的交流然后获得提高。

当然前沿技术接触者也有另外一种做法,很商业的做法,就是译书或自己出书。由于大家都不屑于看那些要摸索去做的东西,而热衷于那些能够抄来就用的东西,所以如果你在前沿技术中摸索出一条路来然后马上写一本实用性很强的书,即使这些实用之处完全没有发挥出技术的优势而仅仅是看起来很Cool,那也会有很多人买去抄,这时候你就能狠狠赚一笔了。这就好比市场上充斥着很多设计类软件的特效书,这些书根本不涉及该设计软件的核心或者说是灵魂,但它就是把最近热门特效的制作方法罗列出来了,然后就很多人去买。

无论如何,这种心态让大多数中国人最终成为了熟练操作一些用烂了的技术的工人,今天制造业上中国是世界工厂,明天在IT行业上也将只能是世界工厂,甚至有些人说仅仅是世界车间,因为先进的工厂也有自己的研发部门和市场部门但中国只有生产线。

2006年8月7日星期一

为了兼容IE把页面的DOCTYPE去掉了

IE浏览我的Blog,总是以左侧高度作为页面总高度,右侧高度多出部分就会隐藏,不知道为什么这样,明明就是符合XHTML 1.0 Transition的。弄了一段时间没搞好,干脆就去掉DOCTYPE,让IE自己用Quirk Mode来解释吧。

试用Microsoft Office Live的服务

很早之前就填写了Office Live Beta的申请,期待着二月能够收到邀请,结果一直没收到,直到最近收到Microsoft的邮件通知才知道已经不需要邀请也能注册了,于是马上跑去注册了一个。

Office Live Beta由低至高分为3个版本:Basics、Collaboration、Essentials,在Beta阶段全部免费,在Beta结束后只有Basisc免费。虽然Office Live暂时是免费服务,但注册还是需要信用卡的,这是为了避免滥用行为,以确保一个在现实中有一定credit的人才能注册一个Office Live站点。开头我注册了一个Basics站点,后来想想既然Essentials暂时也免费,而且MS说明Beta结束时会让你选择是否继续使用收费服务(MS应该不会好像中国的手机服务提供商那么无耻用前期免费服务来钓鱼吧),所以也就选择升级到Essentials了。

成功注册后就可以登录Office Live的Member Center了,快速的翻阅一下所有功能后你就能够快速上手了。在Member Center中你可以选择你的网站的Theme,编辑页面的内容(包括上传照片和文档)。可能由于Office Live针对的是小型企业或大型企业中的小团队,所以它的网站编辑环境都是很傻瓜的,有点像Google Pages那样,不过Google Pages做出来的网页很有个人网站风格而Office Live做出来的网页很有小企业门户风格。

在Member Center中,你还可以配置你的商业应用,这其实是一个类似Sharepoint的系统,可以建立Sharepoint列表,管理你的客户、项目、资源等等的信息。当然你还可以把你的员工的Live ID加入进来,让他们也有权限操作这些列表。如果你的员工还没有Live ID,或者你想为他们分配你的域名下的Email地址作为他们的Live ID,你也可以在Member Center中分配Email地址给他们。

整个Office Live,包括很早就推出了的Office Live Meeting服务,其实都不是MS新开发的东西,这些所谓服务以前都是直接销售的服务平台软件。MS应该知道只有大企业才有足够的资本去购买自己的服务器,然后在自己的服务器上运行这些大型服务并且管理企业内上千台的客户端,所以就提供了租用式的服务,也就是现在大家看到的Office Live。对于使用过Windows Server Family的人来说,Office Live应该是相当熟悉的,里面提供的服务就如一台小型的Windows Server,上面运行着受限Sharepoint Server和Exchange Server。以后随着Office Live的扩展,可能会有根多原本独立销售的服务平台软件变成以租用服务的方式销售。

2006年8月2日星期三

使用 Google Analytics 统计 Community Server 新注册用户来源

很多人用Google Analytics都不会用到“目标”这一功能,可能都以为这项功能是给电子商务网站用的吧。但这其实是一个很好用的功能,能够让你方便的衡量某一特定价值(不一定是金钱),监测该价值的来源。

现在用一个社区(Community Server)来举例,新注册的用户就是一个可衡量的价值。首先进入Google Analytics,在网站配置开启一个新的目标,接着按以下步骤设置:

1.目标地址写上"~/Msgs/default.aspx?MessageID=24",这是显示“注册成功”信息那页的地址,其中"~"指网站根目录的地址,在使用时你必须替代为真实的地址,目标名称写上“用户注册成功”。

2.然后填入步骤1写上"~/user/CreateUser.aspx"和“用户注册表单”,并把必要步骤给钩上。

3.最下面的匹配类型选标题匹配,目标价值输入100。

这样就设置完一个目标了,我解释一下为什么要这样设置:

1.需要步骤1,是为了避免有些用户不是在注册却无缘无关进入了“注册成功”页,然后就被统计为一个成功注册的用户。同时有步骤1的话也就能统计有多少人开始填写注册表单但最终没有完成注册的。

2.设置价值为100,是为了统计数据上好看。在数据报表上,加之为多少也就意味着每100个来源中有多少个人成功注册了。

设置好后等待几天,你就能够在Analytics看看收集到什么了。在已定义的导航渠道你能够看到所有访客中多少进入了注册表单,其中又有多少完成了注册,没有完成注册的转跳到什么页面了。你还能看一下不同的Referrer以及搜索关键字带来的价值,有些来源的用户数量很多但是价值很低,而有些则相反。

最后,如果你愿意改进Community Server的源代码的话,还可以考虑统计其他价值,例如将用户发帖/回贴的字数作为一种价值。

2006年7月26日星期三

初次使用Atlas JavaScript (Part 3 - 实现自己的应用)

在这里,我假设你肥肥的客户端是基于MVC设计,同时Web Service的内容是以数据为中心的。

在说客户端之前,必须先说说服务器端如何设计。如果服务器端你习惯了3层设计,那就保留你以前的数据访问层和业务逻辑层设计方法,用一模一样的方法完成这两层,只不过我们不再有通过Page表现的UI,而是通过Web Service直接暴露一些业务逻辑层的调用,这就是服务器端需要完成的一切。看起来没有了Page轻松多了,是不是?因为那些工作都转嫁给客户端了。接着要开始用Atlas做我们的客户端了,在这此之前你需要读一下Atlas的各种官方/非官方文档,了解一下它的使用方法,同时读一下它的JavaScript源代码了解一下它的内部结构。

我们首先来看看客户端的Model如何实现,客户端Model应该是用来存储数据并和Web Service打交道,所以它应该设计为一个处于客户端的业务逻辑层。然而这不是一个单纯的业务逻辑层,因为真正的业务逻辑在服务器端,客户端的Model仅仅是在客户端暴露和服务器端业务逻辑层一致的调用。同时它也内涵一个小小的数据访问层,这个数据访问层服务则Web Service打交道,需要包括批量调用和数据缓存与索引等能力。现在我们的分层看起来应该是这样的:
Server Data Access Layer <-> Server Business Layer <-> Client Data Access Layer <-> Client Business Layer
我想肯定有人要问,为什么不把整个业务逻辑层搬到客户端,然后就可省去服务器端的业务逻辑层咯,让客户端的数据访问层和服务器端的数据访问层直接沟通就好了。这样做的最大问题就是,你不知道客户端提交的数据是否一定经过了客户端那个业务逻辑层的处理,用户直接提交一些不符合业务逻辑的数据到服务器端就麻烦了。

继续说我们的客户端Model需要具有的能力。例如服务器端业务层有GetProductById这个方法用于返回一个Product对象,同时客户端的Controller也需要调用此方法,那就应该在客户端的Model暴露GetProductById这个方法。最简单的办法,当然是每次客户端执行GetProductById时,都通过Web Service调用服务器端的GetProductById,然而这却是最低效率的做法。想要提高效率的话,肯定要在客户端缓存数据,这时候客户端就会缓存一些Product对象,而GetProductById方法则需要根据一定的策略决定应该优先搜索缓存还是直接访问Web Service。缓存策略是需要根据应用制定的,什么情况下应该判定缓存过期是没有通则的,这需要你自己去设计。而缓存的方式则有比较固定的做法,就是利用JavaScript特有的关联数组作索引。例如ProductId是Guid,而且使用之前说到的GuidConverter直接转换为String,那就可以创建一个Product.IdIndex对象,然后以ProductId作为关联数组的键来保存Product对象,这样就可以通过Product.IdIndex[ProductId]方法检索一个该ProductId对应的Product对象了。

Model相关的对象,例如Product类和Product.IdIndex对象,可以完全不使用任何Atlas特性,仅仅是普通JavaScript类,因为它们完全不使用Atlas的任何特性都能够好好工作。但你也可以考虑让他们继承自Sys.Component,同时按照Atlas的方式来声明其属性、方法、事件,这样他们能够获得更好的封装性,对debug.dump更好的支持,以及可能更低的执行效率。

然后轮到说View了。View可以说是最简单的部分。说它简单,是因为它和服务器端的View没什么不同,只要你懂得制作服务器端控件,你就知道如何继承Sys.UI.Control制作客户端控件,然后和在Page中一样直接往DOM扔控件就可以了,而且还不需要管SessionState和ViewState这样的东西。有问题吗?例如需要数据,或者有事情需要报告吗?请举手,通过调用或者事件告诉Controller,Controller会通过Model为你处理好这一切,View需要管的仅仅就是用户看得到摸得着的东西。

最后需要搞定的就是Controller了,这时候你有两个选择:使用JavaScript或者使用XmlScript。如果Model和View已经让你写JavaScript写到手痛,那么这时候你可以考虑使用XmlScript来写Controller。你首先把View相关的元素用HTML声明,然后在XmlScript中声明相关的控件以及它们的属性如何绑定到对应的Model对象,那就行了。但如果在Controller里面设计动态创建控件,又或者涉及复杂的数据绑定方式,XmlScript就无法满足你的需求了,这时候还是老老实实地用JavaScript写吧。

2006年7月22日星期六

初次使用Atlas JavaScript (Part 2 - Web Service扩展)

Atlas对Web Service两方面的扩展包括:
1.自动生成javascript代理类的代码
2.在javascript代理类调用时使用JSON表达式进行数据交换

通过看Atlas项目的web.config,你可以发现*.asmx现在关联到了一个新的handler,也就是ScriptHandlerFactory,这个handler的行为很简单,如果请求是REST方式则用新的RestHandlerFactory来处理,否则交回给原来的WebServiceHandlerFactory处理。RestHandlerFactory也有一个选择分支,如果请求的是*.asmx/js,那就是请求客户端代理类的代码,使用RestClientProxyHandler处理,否则使用RestHandler处理,下面详细说说它们的原理:

先看看Web Service的引用,当你在ScriptManager添加一个Service引用的时候,实际添加的是到该*.asmx/js的script引用,然后就得到了代理类的代码,之后你就可以直接在javascript中使用该Web Service的类名称(包括完整的namespace)调用,参数列表则和该Web Service的参数列表一致,最后加上一个参数声明该调用的回调函数。RestClientProxyHandler需要生成如此一个代理类,就需要通过反射扫描所有的Web Services函数签名,然后将函数相关的所有类型注册到客户端。这个注册并不简单,因为Web Service有可能涉及任何类型,包括用户自定义的类型。如果是.NET Framework的一些基础类型,Atlas知道如何将它们转换为对应的javascript对应类;如果是Enum,Atlas也能够自动转换为对应的javascript代码;但遇到了不是基础的struct或者object,Atlas自身就不懂得如何将它们转换为对应的,这时候就要寻找是否有对应的JavaScriptConverter了。

JavaScriptConverter是处理服务器端和客户端之间对象串行话/并行话的基类。现在用创建一个GuidConverter的目标来举例,首先通过SupportedTypes属性声明自己支持的服务器端类型为Guid吧,再通过GetClientTypeName返回客户端类型的名称为String,这样RestClientProxyHandler就知道生成代理类时Guid类型的参数在客户端对应为String类型。

接着说说RestHandler,它处理Web Service参数的时候使用的是JSON表达式。和RestClientProxyHandler一样,对于能够处理的类型它自己能够进行串行话/并行话转换,对于不能够处理的参数它寻找对应的JavaScriptConverter帮助。

继续上面GuidConverter的例子,我们需要实现Serialize和Deserialize这两个函数,将Guid串行话为String仅需要这样:
return "\"" + ((Guid)o).ToString("D") + "\"" //o是待串行话object
而将String并行话为Guid则仅需要这样:
return (new Guid(s.Replace("\"", string.Empty))); //s是待并行话的String的表达式
最后在web.config的converter节注册一下GuidConverter,Web Service就能够正确的和客户端交换类型为Guid的数据了。

系统自带的JavaScriptConverter包括DataSetConverter、DataTableConverter、DataRowConverter,注意这3各类都没有实现Deserialize所以仅能用于将数据传送到客户端。

初次使用Atlas JavaScript (Part 1 - JavaScript扩展)

Atlas的服务器端控件已经说了,现在说说客户端脚本。Atlas的脚本分为xml-script和javascript两部分:xml-script作为一种描述性语言主要用来做Controller,直接放在页面里面;javascript经过Atlas库扩展后可以用来写Atlas特有的客户端控件,而其内容最好放在独立的js文件中通过引用来使用。xml-script我还没有专门研究过,不是太懂其机制,所以现在先说说其javascript扩展。

首先,Atlas对javascript语言本身作了一定的扩展,例如让javascript支持继承,还有抽象函数、寒暑重写等概念,可以说是极力模仿C#风格。这对于习惯用C#的人来说是好事情,而且内联而非prototype方式声明外露函数和属性也确保了内部变量的不会被外部访问到,从而确保了类的封装性,但这样做却让Altas的执行效率显得比其它framework要差一些。另外Atlas还对javascript本身的String、Array、Date、Number作了简单的扩展,目的是为了模仿.NET类库对应的类的常用方法,方便javascript编写者。关于Atlas对javascript的扩展,详细可以参考这篇ASP.NET Atlas对JavaScript的扩展。(由于Atlas还在不断改进中,无论是官访文档还是自己研究Atlas源代码者写的文档都仅仅是关注到作者认为应该关注的方面,所以资料不一定全面,而且还不一定适用于日后的版本,所以最好还是使用时参考Atlas的源代码。)

当然,Atlas不可能全面扩展javascript的对象让他们拥有所有服务器端对应对象的常用方法,这时候你就需要自己扩展了。例如Date对象没有AddYears等方法,而你的程序需要这方面的Date对象操作便利,你就可以模仿着服务器端的方法去写对应的方法。模仿的最简单办法就是用Reflector打开.NET Framework看,看看它是怎样实现的,然后你改用javascript实现。由于.NET Framework系统类的实现方法效率不可能太低,所以按照它的方法去做效率应该也不会差,不过你自己有更高效的方法就更好了。

2006年7月19日星期三

Atlas 的服务器端控件 - 易用但不灵活

首先,我会把Atlas服务器端控件区分为两类,纯服务器端控件和客户端逻辑封装控件。前者类似WebControl派生出来的控件那样,它自身并非直接呈现(render)一个客户端元素的实例就算,而是拥有复杂的服务器端逻辑,它呈现出来的HTML由交错的规则决定着;至于后者,则类似HtmlControl派生出来的控件,它所做的基本上就是将自身呈现为一个单一的客户端元素,其服务器端属性比较直接的生成客户端元素的属性或者子元素,不过客户端逻辑封装控件输出的不是HTML,而是Atlas特有的xml-script。

纯服务器端控件是Atlas服务器端的重点,这些控件在Microsoft.Web.UI而不在Microsoft.Web.UI.Controls,由此也可以看出他们的核心地位,它们是ScriptMananger(ScriptManagerProxy)和UpdatePanel。

首先说说ScriptManager,它都是一个非常有用的控件,扔一个ScriptManager到Page上面,它就会自动帮你生成引用Atlas核心js的引用,这样Atlas函数库就能够被使用,xml-script也能被解释。对于一个ScriptManager,你可以向它添加Script和Service引用。

可添加Script引用的包括Atlas内置的Script模块(AtlasUIDragDrop、AtlasUIGlitz、AtlasUIMap)和是你自己的js文件,如果添加的是js文件你可以使用"~"路径运算符以确保无论在什么路径的页面都能正确引用这个js文件。

添加Service引用的Service是ASP.NET Web Service,添加引用后你可以直接在JavaScript或xml-script中调用该Web Service而无须管后台是怎么实现的。另外,ScriptManager还有一个重要的属性,就是EnablePartialRendering,启用后ScriptManager就会去分辨一个PostBack是正常提交的PostBack还是XMLHttpRequest发回来的异步PostBack,如果是后者它就会优化处理,详细下面再解释。

然后说说UpdatePanel,这就是Atlas让你最容易开发一个“看起来很Ajax”的应用的地方。所谓的UpdatePanel,其实就是圈定一个区域,里面的控件或者外部注册为异步调用的控件触发PostBack时并不真正提交页面而是用XMLHttpRequest发送异步PostBack,之后分析从服务器端返回的HTML并更新这个区域内的HTML代码。你可以设置一个UpdatePanel不是每次都需要更新内容,当一个异步PostBack发生时就根据一堆的Trigger设置来判断一个UpdatePanel是否在本次异步PostBack时需要更新,同时ScriptManager开启了EnablePartialRendering的话则只有需要更新的区域内的HTML才会被发送到客户端,这样就可以节省沟通成本。

虽然这样看起来UpdatePanel非常灵活,区域有多大以及什么条件下才更新都能够设置,一眼看起来设置适当的话非常好用。但其实并不存在“设置适当”,UpdatePanel并不是万能,它不能像普通控件那里放在任何区域之内、包容任何控件、在页面生命周期的任何阶段声明,所以不是你喜欢怎样放就怎样放。而且当UpdatePanel多起来Trigger也不容易设置完美,总会导致应该更新而没更新的情况,而那个时候你就会想还是把所有UpdatePanel设置为总是更新算了。

UpdatePanel最坏的地方我认为是破坏对象结构。服务器端控件和客户端的DOM都是树状结构,目标就是保持逻辑的局部性,所以Response.Write和Document.Write这种破坏局部性的操作方式我觉得都不应该被使用,而UpdatePanel区域的刷新就如Response.Write一样,一刷就是整个区域。虽然在服务器端区域内的还是控件,还是可以按控件进行逻辑处理,但是在客户去这样一刷,DOM元素都被破坏掉了,区域内增加删除修改了哪些DOM元素完全没办法知道,这时候该区域内外的View和Model都独立,要建立一个跨越区域边界的Controller也不容易,当内部的View和Modal被整个替换掉的时候,Controller完全不知道变更的细节,而需要自己去适应新送上来的View和Model。对此暂时我觉得可行的解决方案就是建立一个内部的Controller,让该Contoller负责和外部Contoller的沟通,而该Controller由服务器端生成,所以它可以知道新旧的View和Model之间的变更细节。

简单来说,用UpdatePanel就如用不闪烁的IFrame一样,传统的做法能够马上用上,但效率不高,灵活性也低,最后你会发现不如整个页面都放在一个大的UpdatePanel里面,让它“看起来不闪烁”就算了。

2006年7月7日星期五

ViewState - ASP.NET 的一个特有存储容器

首先,我不确定是不是只有ASP.NET由ViewState,也不确认它有多特有,只是觉得这个东西对于Web开发MVC分离的进步很有帮助。

所谓的ViewState,就是用来存放关于View的State的地方。以前的存储容器包括Cookies, Session, Application, Cache, Hidden,有时候连传递变量用的QueryString也用作存储容器,但都不是专门用来存储View相关信息的地方,然而由于没有专门存放View相关信息的地方,所以人们只好乱放。不怕过期失效的变量,多数人会选择放在Session里,而且跨页面不会丢失,用户访问几个别的页面回来还能通过Session恢复本页的View。如果需要延长一些时间,而数据又不是很多的话,可以放Cookies,和Session类似。而数据真的很短,而且页面总是提交给自己的情况下,用QueryString作为一些跨页面生命周期的变量的保存方式也可以。而如果页面可以只用Post不用Get传递的话,那么Hidden也是一个很好的选择,因为Hidden容量大,不在地址留下信息。在ASP.NET当中,就是设计到大多数情况都是Post(除了直接链接),所以用Hidden存放和View相关的信息是非常适合的。

既然用Hidden存放就可以了,为什么需要ViewState这样的统一管理呢?最显然的理由就是加密。ViewState不是给用户看或者修改的信息,仅仅是因为View的状态会在页面生命周期之间丢失,所以我们要将这些信息输出到HTML再等Post的时候取回来,对ViewState加密(至少校验)能够确保View正确无误的恢复。ASP.NET内置的ViewState可以方便的设置校验和加密,只要你把可以序列化的对象存进去,它就能够自动序列化并输出到HTML,同时该对象的保存与恢复是跟控件名以及在控件树中的位置相关的,就如ASP.NET控件的其他特性一样,确保了树中不同位置的同ID控件的数据不会被混淆。简而言之,ViewState是保存跨页面生命周期有关变量的最好容器,但它又不能够跨出页面范围称为会话变量的容器(那应该是Session负责的哦),所以是真正符合其名称用来保存View的State的。

有很多ASP.NET的新手不知道ViewState的用途,认为它是ASP.NET的内部对象,平时还是仅用ASP那套公开的对象好了,那就会带来很多麻烦。例如有GridA和GridB两个页面,点击一个条目查看明细都回转到Details页面,同时Details页面要提供返回原来页面的途径(包括原本GridView所浏览到的分页)。如何存储原本页面的状态呢,包括它来自GridA还是GridB以及原来的GridView所在的分页?有人选择用QueryString传递给Details页面,让Details页面构造返回链接时再通过QueryString把状态传回去。显然,原来页面的状态不是对Details的Query(查询),那么用QueryString传递给Details页面是不合适的。也有人选择用Session传递,但是这个状态仅仅做一次传递,难道我对你说一句话也算是Session(会话)?当然不算。用Hidden是一个方法,但是基于我上面所说的ViewState对Hidden的改良,在这种情况下就应该用ViewState作为原本GridA或GirdB的View状态的保存方式,并且在经过Details页面返回之后再还原。需要说明的是,只有ASP.NET 2.0才在内部支持跨页面PostBack,ASP.NET 1.x不支持跨页面PostBack,也无法跨页面接受和保持ViewState。

最后就是使用ViewState需要注意的地方。过量使用ViewState当然有损效率,但这对于网站的数据正确性来说还不至于造成漏洞,真正会造成漏洞的就是ViewState重名。上面不是说了ViewState是根据控件树位置和控件ID保存所以不会重名的吗?在树是静态的情况下确实是这样,但是如果树是动态创建的,而ID则是可能在不同的语义下重复使用的,那就可能破坏数据的正确性了。例如一个DataControl的子控件自动命名为Control_1, Control_2, Control_3等,如果在PostBack后该DataControl被再次DataBind,那么DataSource可能已经改变了,所以需要清除所有的子控件并重新根据DataSource创建它们,此时别忘记了调用ClearChildState方法把子控件的ViewState和ControlState都清除掉,否则当你重新创建子控件而它们的名称还是Control_1, Control_2, Control_3等的时候,就可能会把原来的ViewState加载回去。

2006年7月1日星期六

OpenID - 继claimID之后

首页在这里:openid.net

OpenID的目的是一个真正的分布式Identity系统,可以用于验证你是某URL的Owner。在范例中,它假设你有一个Blog,然后你在另外一个支持OpenID的Blog发表评论,在评论后你就可以输入你的OpenID登录。所谓你的OpenID,就是一个URL,例如你的Blog的URL。在收到评论提交和OpenID后,该Blog系统就会去你的URL检索OpenID信息,并到指定的OpenID服务器验证你的登录,验证成功就确认你是来自该URL的用户。

如果用过Google Sitemaps,你就知道要查看该站点的统计信息必须先确认你是该站点的Owner,而方法就是Google会要求你对该站点的首页插入一个指定meta标记,然后Google检测到该标记后就确认你是该站点的Owner了。Google Sitemaps是由Google统一确认你的Owner身份,而OpenID则允许你在你的页面中通过<link rel="openid.server">指向任何一个OpenID验证服务器,这就是它所谓分布式的地方。至于指向的Server通过何种方法确认你是该URL的Owner则是不确定的,例如如果该Server就是你的BSP(Blog Service Provider),那么你提供你的Blog的URL和密码它验证,这是很简单的事情。

2006年6月27日星期二

ASP.NET 设计优秀之处

我觉得ASP.NET设计得最好的地方,就是控件树的概念。虽然WebForm的概念很烂,误导了不少没有Web开发经验的程序员,但它带来的控件这一概念及控件树结构就真的很好。

控件树优秀的地方,就在于它把整个页面的处理逻辑分割到控件,控件与控件之间是松耦合的,不存在任何依存关系。以往的Web开发,所有的代码都是平板式的接受Request平板式的输出Response,Request被看作由不同的Request属性组成,Response被看作不同的Response片断,而这些由平板式的代码混合在一起处理,导致Request属性和Response片断之间的耦合度很大。而在ASP.NET中,一个控件就只取它需要的Request属性,然后对它输出的Response片断负责,那样就相当于解耦了。

如果两个控件之间存在一定的逻辑,这些逻辑就应该交给一个可信赖的第三方统一管理。一般情况下,这个第三方是父控件,因为父控件有权统一管理子控件的行为,所以子控件之间的交互逻辑也可以交由父控件处理。另一种方法是通过专门的控件负责,例如WebPart之间的逻辑(WebPartConnection)统一由ConnectionsZone管理。控件间逻辑集中在一个地方,统一管理,需要时统一根据涉及控件的存在性判断丢弃该部分逻辑或者抛出异常,这还算是一定程度上的松耦合度。

有很多ASP.NET的新手,特别是有ASP经验的,一上来就喜欢用Response.Write输出一些无法用控件输出的信息,其实这是不对的,任何一类信息都应该由专门负责的对象负责输出,如果不存在该类对象你就要自己制作一个负责此类逻辑的类。用Response.Write输出debug信息是常见错误,实际上应该开启Trace然后用Trace.Write或者Trace.Warn来输出debug信息。用Response.Write输出script也是很多人在用的方法,实际上应该用Page.ClientScript下面的RegisterClientScriptBlock等专用script注册函数。至于输出的是HTML的话,则绝对不应该用Response.Write了,如果没有任何控件能实现你要的输出逻辑,就自己写一个,按照自己的逻辑写Render,Render就是专门给你书写自己的局部HTML输出逻辑的地方,而且在Render中你最好用HtmlTextWriter的特有方法来输出HTML,因为那样做能够比较容易将Render的代码迁移到别的Mark-up Language输出环境。

2006年6月20日星期二

学习应该追求“游刃有余”的效果

“游刃有余”这个词是从哪里听来的呢?是某年GDKOI听郭嵩山(中大搞ACM兼负责广东省OI的那位)说的。他当时要表达的意思是,中大不会保送仅仅是竞赛好的学生,你必须平时学习也好才行,因此他说必须平时学习游刃有余才好搞竞赛,否则还是专心学习好。当时我就觉得这句话应该将因果倒置一下才更真实反映现实,那就是你平时学习保持在游刃有余的水平就够了,这样你才能够在竞赛方面有所发挥。

后来见到Coo的del.icio.us收藏了一篇文章,标题大概是“让一个人失去创意的最好方法就是让他超负载工作”。然后最近ziyan又说,Benny对着教学处主任说“想发展兴趣的学生是不能参加高考的”,于是我决定写一下这个题材。

“参加高考”指什么?当然不是指高考这几天的考试。我也去高考了,但对我来说无非是玩下,成绩也不入档案,更加不存在复习备考,所以不算“参加高考”。“参加高考”指的是由于高考而由高考那天此向前延伸1年的全年备考,甚至再向前延伸0至2年的部分自由的剥夺期,而这1至3年的时间里,你就处于那种“超负载工作”的状态下,所以“参加高考”实质上指的应该是至少1年的“超负载工作”。

然后有人会说,“不是啊,我高三很轻松很堕落啊”。这时候我觉得就有必要将“让一个人失去创意的最好方法就是让他超负载工作”这句话向广义推进一下,让主语变为“一群人”。由于你所处的群体处于“超负载工作”中,而创意往往是需要通过讨论、阅读等途径激发灵感,正如一个处于低温物体中的粒子一样,即使它有一个时刻处于高能状态,它也只能将能量散发出去,而不能长期处于高能状态。

如果一个学生能够让其学习保持在“游刃有余”的状态,无论他学习怎样,他总能够将他剩余的能量发挥到创意上面去,这才叫做“发展兴趣”。至于“发展兴趣”好不好,这就要看个人了。有些人天生喜欢跟大流,那是没得说的。有些人“发展兴趣”结果更好了,自然有些人结果更差了,这属于正常现象,否则所有人都去“发展兴趣”了。Benny说过,如果高考是独木桥的话,竞赛就是峭壁——很宽很宽问题只是你是否爬得上。

最后,就是必须区分“游刃有余”和“好吃懒做”。“游刃有余”并不能成为“好吃懒做”的借口,否则你将剩余力量都浪费掉了结果就当然比“超负载工作”要差。

2006年6月7日星期三

为什么 BBS 在中国那么火 (Part 2 - 社区生态学)

好了,抛掉那些有暴力没美学的沙子,继续挖掘论坛的金矿。社区研究之BBS的死亡鉴定里面的理论是"火了-水了-完了",感觉对于大多数公开论坛都正确吧,但其实这里讨论的都是仅做内容服务的论坛,人们来论坛的唯一目的就是论坛里的内容,所以必须以内容养内容。但是对于不用以内容养内容的论坛来说,例如提供下载服务的TLF,因为人们是为了下载而来的,所以即使内容不怎么样也会有相当的流量,流量多了自然有人发言,发言多了既然有精华,然而即使水了也不会完了,因为流量仍在,水多水少好像一个生态环境那样自然平衡,而下载服务就好像绿色植物那样维持着食物链的存在性。

还有一些看起来不完全是以内容养内容的论坛,但又没有绿色植物的,例如一些下载交换论坛。所谓交换,就是下载不是由官方提供,而是靠大家上传,如果人都走了同样论坛会死掉。不过这样的论坛有一个好处,就是文字内容不是价值的主要来源,价值的主要来源是上传,这时候哪些内容有价值哪些内容没有价值是非常容易区分的,也就一定程度上避免的水化这个过程。

讲到内容价值,就不得不讲精华贴这个设计。这个设计是用于奖励发贴者的吗?初衷可能是,但结果绝对不是,精华贴的作用是为了浏览者尽快找到他们要找的东西,即使他们在无聊闲逛也尽快为他们提供有新鲜的有价值的事物让他们结束无聊阶段。看看TLF,已经不仅仅是有精华贴了,而是贴子分等级了,普通贴子普通颜色,不同类型的"公务贴"用不同颜色的粗体显示,让你一找就找到你想要的东西。例如在字幕区吧,发布字幕的贴子为绿色,而求字幕或者讨论字幕的贴子则为普通的黑色,这样找字幕的人一眼就能够找到字幕。即使你通过电影名称搜索字幕吧,搜索结果里也会用绿色把发布字幕那一帖显眼的显示出来,当然还可能看到蓝色的显眼贴,那是测评。有些人说论坛社区是按主题聚合,Blog社区是按人聚合,什么聚合有什么特点,但现实是——只有你想不到的聚合形式,没有实现不了的聚合形式。TLF那样把不同版面同一类型的公务贴同一颜色标记,也算是一种对内容的聚合形式,不是吗?

回到生态学的问题上,既然说到了论坛社区和Blog社区,那么就开始用社区这个词而放弃论坛这个词。越复杂的生态系统就越难建立,但建立后就越能够抵抗外力,如果一个社区构成部分相对复杂一些,例如包括论坛、电台、下载、测评,那么即使一方面受到外力的打击但仍能维持流量,要恢复并不难。社区上各式各样的用户,就如各式各样的生物,有产出有消耗,但只要一个社区能够维持食物链的稳定性,那就能够幸存下去。然而很不幸,数量最多的是那些食物链顶端的终极消费者,也就是那些仅消费不贡献的(例如长年潜水的),反而最少的是绿色植物,也就是那些需求低了与无偿贡献的。由此看来,如果单单由用户构成一个封闭的生态系统,基本上是死定的,必须依赖于与外部的交换才可能让这个生态系统运作下去。如何算是和外部交换?例如用户可以选择付费,然后这些费用最终转变成一些收费信息的来源。

为什么 BBS 在中国那么火 (Part 1 - 整理及评论)

王冉的原贴在这里:为什么BBS在中国那么火,这只是一个起头,但它提到了一个"先进性"例子:"在国外(至少是在美国),虽然也有一些所谓的论坛,但是往往都是围绕一些窄众关心的具体话题,譬如某个学术问题、某部电影或者某款新电脑",这用于下文评论douban。

keso的东拉西扯:为什么BBS在中国那么火,我觉得既然要提早期Internet,就必须把概念分开来——BBS和Forum是两样不同的东西。虽然他们的很多特性看起来都一样,甚至使用起来也完全一样,但基于历史的原因我还是习惯把它们分开。BBS是Internet早期的产物,那时候还没有Web,消息都来自BBS,在当时的情况来说,BBS就是Internet的绝大部分,而后来的Forum则仅仅是Web的一种使用方式。BBS有一种特性,就是不可替代性,在那个时候你要获取信息就要通过BBS,你不能选择不用BBS或者用其他形式。从名字来看,BBS是电子公告版,而不是论坛,这就让BBS看起来有点官方色彩("官方"在这里指理想中的人民自愿放弃其部分政治权利而授权形成的政府)。至于为什么BBS后来在中国习惯被翻译为论坛,这可能就是问题的根源了,也就是论坛特性加上民族特性所造成的结果。

麦田在社区(1):聊天室启示录中,提到了论坛的技术零成本和言论零成本特性。技术零成本这没什么好说的,任何一个易用的产品都必须具有这样的特性。言论零成本,才是真正和民族特性结合的地方。因为中国人习惯了隐藏自己的欲望,特别是那些显得有点“坏”的欲望,然后又不同于菩提树下的顿悟——“我选择没有欲望,因此没有欲望满足不了的痛苦”,中国人会选择在适当的场合释放这些欲望,而且有可能是加倍的或者以变态的形式释放这些欲望。于是论坛就成了这样一个场所,和五谷轮回之所一样。“你有压力,我有压力”,“未解决”?那就去释放一下咯,只不过前者用于释放言论的压力,后者用于释放膀胱的压力。

中文BBS:红旗下的蛋中,麦田还说到了“网络暴力”的问题,他总结网络暴力的4大特点,看完后我真的想说——网络暴力现在主要发生在网上,那实在是一大进步啊!(他这里所说的“网络暴力”应该仅指论坛言论上的攻击。)回想一下,我们花了某十年时间去进行“现实中的网络暴力”,其特点也一定程度上符合那4点,那个伤害大啊,死了多少人经济损失多少,而现在这种单纯在网上的网络暴力,幸运的话仅伤你的ID(甚至仅伤马甲),不幸的话才伤到你个人,但至少不会搞出人命。

为什么论坛能够在这种事情上那么热?因为它提供了一个“无代价战场”。有那么多自称“爱好和平”的人士,正如我所说,他们需要释放他们对暴力的欲望,这个特定场所最好就是一个无代价战场。其实无代价战场有很多选择,不过Battle Field对于很多人来说都太具有战略性,GTA的英文剧情又不那么容易懂,这时候论坛的技术零成本就绝对会让它中标了,就那么简单。

2006年5月22日星期一

还是喜欢工作两个月玩两个月的生活

以前习惯了,连续两个月很有热情的投入一个项目,改设计写代码,两个月之后就累了就不想做了,就算没做完也没激情了。然后开始打机,很专心的玩一个游戏,大概玩两个月又发现这个游戏不过如此,就回去做项目了。(Coo好像说过他也是这样。)

从寒假开始,接外面的东西做,其实平均下来一个月就¥400,也就是¥400分量的工作(就是隔几天做一点也行的那种),但是连续做几个月就很累,想放松,完全不想写代码。当然这也和最近写代码的方式有点相关。

以前用ASP写代码,虽然不算得上面向存储过程(因为Access根本没有Stored Procedure这个概念),但也差不多吧,反正就是我需要什么样的SQL语句,就写怎么样的,用得多的SQL语句就封装起来成为一个VBScript Function。现在用ASP.NET 2.0,尝试按照TimeTracker Starter Kit那种简单的3层架构写,但就发现写类代码就真的很累,或者应该叫做“累代码”。首先,看起来把逻辑都封装成累,对于UI代码来说是很爽的,因为UI代码再也不用管持久层需要怎样格式的数据,反正就是组织对象,用对象方法来存取数据,那就行了。但是写类代码时就会比较头痛,因为重复写那些Property并不简单,而调用方法基本上就是直接调用当前DataProvider的同名方法然后把数据传递过去。到了持久层,也就是DataProvider,需要进行类与平板的关系型数据进行交换,也是很头痛的,其实UI表现本来也是平板的嘛,对一层立体转换并不好过。还有就是,直接用存储过程可以使用一些复杂的,例如SELECT ... IN (SELECT ...)这样的嵌套语句,但是如果要先获取内SELECT的对象集合,然后for/foreach循环来获取外SELECT结果,那就惨咯。

据说有一些中型项目的项目经理还是偏好于面向存储过程设计,而不是面向对象,不知道大家看法如何。

2006年5月15日星期一

VeryCD做开放式中文IMDB以及吃素网站

http://base.verycd.com,和IMDB非常类似的功能,主要按照作品、人来收录,然后链接作品和人的关系(例如导演、演员、配音)。不过IMDB的资料(特别是照片)都来自官方,或者专业记者,能够拿着Invitation甚至VIP证出入各种尊贵场合的那些,而VeryCD的照片则靠网友上传。

不过VeryCD的资料应该是自动从IMDB同步获取的,所以看上去更加像一个“IMDB中文外挂”。也就是说,VeryCD从IMDB的网站获取所有IMDB的文字资料,然后同步到自己的数据库,同时在自己的数据库增加IMDB没有的字段(主要是电影/演员中文名和中文简介之类的字段),然后评论是VeryCD的而不是IMDB的。还有就是,用户能够好像修改wiki那样修改VeryCD上的资料,但如果用户修改了资料然后IMDB也更新了资料,那么是不是又用IMDB的覆盖,那就不知道了(反正就是wiki类的东西,覆盖来覆盖去都没所谓)。

正所谓弱肉强食,那些靠养着一群编辑的网站已经变成绿色植物成为了食物链的源头,过去dot-com的投资已经足够多也就造成了绿色植物过多,现在是时候为了平衡一下生态环境削弱一下它们的优势了。所谓的食肉动物,就是那些打着share或者aggregate旗号直接利用别人站点内容的站点,把植物拿过来消化一下,然后变成自己的组织和能量,真是个不错的主意。既然现在绿色植物过剩,那么在接下来一段时间做做吃素网站也不错,起码不用养着一身的叶绿素,吃就行了。至于再以后,就想想办法如何做肉食动物吧,那是以后的事了……其实我是很赞成研究企业生态学的,如果一个企业能够维持好和其他有利害关系的企业的关系,不把自己的食物吃紧,同时又保证有天敌存在帮忙吃掉一些自己的同行竞争者确保这一样不过过度繁殖,那就够了。

2006年5月13日星期六

ClaimID.com - 声明哪个是你

很有趣的服务,我是听Inside the Net的podcast听到的,可以来看看Inside the Net主持人Leo Laporte的页面:
http://claimid.com/leo
又或者ClaimID负责人之一的Fred Stutzman的:
http://claimid.com/fred

因为在线有很多同名称或者同ID的人,甚至有些是恶意冒充你的名字和ID的情况,于是有了claimID这样的服务——注册一个页面,声明哪些页面是我的或者提到的是我(例如我发布在各处的blog、我参加的项目、别人对我的评论),当然还可以声明哪些不是我。甚至,你把你的公钥(例如PGP Key)发上去也可以,这样别人就可以随时到该页面下载你的公钥,用于解密你发给他的邮件,或者其他加密信息。反正只要是URL,你就可以发上去,类似del.icio.us,不过你不是声明该URL的内容性质如何,而是该URL与你的真实身份有什么关联。

顺便说一句,我的claimID页面在这里:
http://claimid.com/cat

2006年5月6日星期六

英语国家开发人员总是不注意Encoding的问题

英语国家开发人员通常都不考虑需要Encoding的情况,因为他们开发的软件不需要Encoding,也不一定有机会测试Encoding,这真是麻烦。

任何一段开源代码到手后你首先要考虑它是否涉及文件读写或者HTTP收发等操作,如果涉及,就必须考虑Encoding,特别是对于有多种Encoding方式的语言(例如中文有)。如果很不幸那段开源代码对Encoding没有支持,那么你就必须自己动手去增加Encoding的支持。

如果Encoding涉及的地方只有几处,那改就是了。如果Encoding遍布整个代码,那就几乎不是改的问题了,而是重写,哎……做开发不能不懂Encoding,但Encoding实际上又真的是一个大问题。有很多与计算机架构有关的问题仅限于某些计算机,因为只有那类计算机使用该架构而需要考虑该架构的问题,这是很灵活的。但是字符是任何计算平台都要交换的,不可能强制要求所有平台都转用Unicode或者一种指定的Encoding,于是设备与设备之间沟通就必须支持Encoding之间的转换。优秀的设备(例如PC)必须支持多种Encoding共存,所以运行在这些设备的软件业需要有处理多种Encoding的能力,这看起来成了一个永远无法解决的问题……

2006年4月30日星期日

设计一个面向Photoshop用户的CSS设计器,应该很畅销!

很多美工,还是习惯用Photoshop设计页面然后Slice,这样的设计方式对他们来说比较直观,不需要在脑袋里想着效果然后写HTML和CSS然后再看实现得如何。能够脑袋里想着结果然后闭上眼睛写代码的,估计主要还是程序员,美工需要能够看得到摸得着一步一步去fit的东西。虽然现在也有些美工人员在尝试摆脱HTML table排版改用CSS,但是用Photoshop输出的table改div和CSS既不方便结果也不一定是最优的(相对能够闭上眼睛写HTML+CSS的人来说)。于是,我就想如果能够开发一个有点类似Photoshop那样的绘图见面,但又能够直接用于设计CSS的设计器,应该会很多人喜欢。

其实Frontpage和Dreamweaver已经很“所见即所得”,专门的CSS编辑器如TopStyle也是能够编辑CSS的同时显示效果,为什么还要像Photoshop那样?因为我觉得美工是靠feel工作的,例如导航栏的高度和文字定位,你要求美工修改一下height然后又调整一下padding和margin,尝试一下px做单位,又换用一下%做单位,这应该是比较痛苦的事情。人家在Photoshop里面,导航栏高度喜欢拉多高就拉多高,文字定文也是用鼠标放,这完全是靠看着整个页面的构图感觉来做的,对着一堆CSS改一下代码再看一下结果就很不爽。所以,这个类似Photoshop的CSS设计器一定要完全实现在可视化界面上实现所有操作,也就是说用户也是直接通过拖动就能够实现字体定位的,至于margin和padding就让设计器自己去管理,没必要让用户操心,用户最多选一下按px计算还是按%计算然后看看不同情况下变化的效果。

要说明的是,因为美工面对的往往不是一个fixed的页面,而是随浏览器可视区域变化而变化的页面,所以设计器本身应该支持不同可视区域大小的preview。例如我当前在1024*768可视区域的模式下设计,但是旁边有缩略图显示这个CSS在800*600中的显示效果,通过鼠标放置字体位置后,改变按px计算和按%计算不会影响1024*768模式下的效果(因为这是当前设计模式),但是800*600模式下的preview就会跟随改变,因为当前的设计效果按照不同的单位来定位的话在其它模式下的显示结果是不同的。

这个设计器的重点,应该就是div和ul的放置了,因为这两个东西现在用得最多。div的放置应该支持dock(停靠)的效果,或者是现在WinForm所支持的anchor效果(比dock更好)。在说这个之前,大家可以来看看一个在线的CSS Creator的效果:
http://www.csscreator.com/version2/pagelayout.php
这个东西允许你设置常见的排版模式,例如有没有Header和Footer,它们的高度多少,按px还是按%算,body部分分为几个column(最多3个),宽度又如何算,页面的最大最小高度如何。我所谓的div支持dock,就是类似现在主流所做的那样啦,3栏结构的话,左栏dock左边、右栏dock右边、中栏占满剩余空间(这不废话),如果超过3栏也能dock/anchor的话就更好了。anchor是一个比dock更好用的东西,dock只能依赖于4页面边缘,anchor则是任何一个控件的4边缘都可以依赖于仁和另外4个附近控件的边缘,如果CSS能够实现anchor效果就好了。另外就是要有一个preview显示无CSS时的效果,能够看到完全无CSS时出来的样子如何。

2006年4月21日星期五

ASP.NET 2.0 的编译模型并非完全像 MS 说的那样

上次说到了ASP.NET 2.0解决了Code-Behind需要同步声明控件的问题,说MS的图例解释2.0中aspx和cs的内容不再是继承的关系,而是partial的关系,是合并编译。然后我说了,如果是partial关系,那么处理过程就很复杂。因为partial不能增量编译,也就不能跨语言编译,必须把aspx部分内容完全翻译为cs或者其他对应Code-Behind语言,然后才能够多partial一起编译。但实际上当然不是这样做,现实中aspx既是partial,又像1.x那样要做为继承类再编译一次。

发现这个问题,是由于我在cs声明了一个private的函数,想在aspx中的数据绑定语句中使用,结果调用时竟然告诉我找不到该函数,然后我把private改成protected就可以了。如果aspx和cs真的完全是partial关系,那么private函数是能够找到的,private找不到说明aspx中数据绑定语句和cs肯定不是在同一个类中,也就是不是partial关系,而是好像1.x那样的继承关系。实际上,我说的aspx完全翻译为Code-Behind所用语言应该是做不到的,最多把aspx中的所有服务器控件声明翻译。因为都是声明,可能如果一个partial里面有的只是声明,那编译器内部就支持增量编译,因为声明在编译结果里就是一个比较独立的部分。然后aspx中的其他逻辑都是好像1.x那样,再继承编译好的Code-Behind代码,把UI代码加上去。

2006年4月5日星期三

监视你的用户

正如之前的StealthMeter或者GamePlaysMan一样,我时不时都利用流行的技术和设计想出一些坏东西来,这次轮到Keep Your Visitors Under Surveillance了,咔咔……为什么那么多个词不用,偏要用Surveillance,因为我就想做到好像闭路电视监视网一样的效果,能够在中央控制室同时监视多个用户,而且要是实时的。

Analytics和MeasureMap出来了都还没有机会用上,就又听说有一个新的更强的站点分析平台能够分析用户鼠标在页面不同部位停留的时间长度,然后用不同的颜色把鼠标停留时间的梯度显示出来,虽然实际效果如何还不知道(该平台还在Alpha阶段),不过通过用户鼠标停留时间应该能够看出用户的阅读方式(还是有不少人习惯用鼠标跟随目光的),以及用户对页面的哪些链接感兴趣(即使没有点击)。另外最近也看了Sliver(1993),觉得在监控室中对着满墙的监视屏幕看着不同房间的人在做不同的事会挺有趣,于是就产生了监视Web用户这个想法。

首先,要实现一种ClientViewState,也就是客户端的ViewState。和ASP.NET的服务器端ViewState用于保持页面生命周期间View的状态不同,ClientViewState就是显示反映客户端浏览器当前的状态,例如页面滚动到何处,用户鼠标停留在哪里。这个ClientViewState要是实时更新的,也就是客户端的所有操作相应都实时更新ClientViewState,对于好像鼠标移动这样的事情ClientViewState会产生Frame,而对于点击这样的更新产生KeyFrame,Frame和KeyFrame会使用Ajax模式直接传输到服务器以更新服务器端存储的ClientViewState,再传输时KeyFrame拥有更高的优先级,一旦产生KeyFrame则KeyFrame之前产生但未传输完的Frame就丢弃,仅当没有连续KeyFrame时才传送Frame。

然后,监视页面从服务器下载ClientViewState下来(使用Comet模式),把每一个ClientViewState释放到一个对应的IFrame,在该IFrame还原对应的被监视用户的当前ClientViewState,通过IE的DOM的按百分比缩小显示功能把IFrame内的内容缩小,这时候监视者就可以在监视页面看到用户实际操作的情况了。

实现ClientViewState不是难事,现在的DOM足以应付,然后把ClientViewState串行话传导服务器端然后再传到另一个客户端并还原也不难,关键就是传输途中用的Comet模式是否有效率。所谓Comet模式就是现在Talk in GMail和Meebo等WebIM采用的Ajax模式,和普通Ajax唯一不同的就是Comet使用keep-alive的HTTP连接从而实现服务器端主动Push数据到客户端,但到底这样的长连接能够应付多大的负载我实在还不知道,不过应该应付串行话的ClientViewState传输还是绝对没问题的。

至于实时监视有没有什么意义,这个我暂时不知道,对于成熟的站点来说可能没什么意义,但是对于Beta阶段需要知道用户使用方式的站点来说或许有用,正如软件易用性测试可以用走廊测试一样(在走廊上随机拦几个人来试用你的软件然后看他们的操作方式),你可以通过监视用户如何使用你的站点从而知道易用性方面是否有问题,同时也无需让用户填一堆关于使用方式的调查问卷。

2006年4月3日星期一

LoadPostData 最多只有两次

在很多MSDN的一般文档中,都回避了LoadPostData这个问题,直接就说Page由Init到Load然后就是控件事件了。而根据我的实验,在Load的前后会出现两次的LoadPostData,而最后在MSDN也找到了独立的文章证实了这个流程。

一般的HTML中静态声明的控件初始化应该发生在Init,Init之后这些控件也就初始化完成。然后此时会有一次LoadPostData,这是面向仅使用HTML静态声明控件的情况,这样在Load的时候这些静态声明的控件就已经成功加载了数据,可以直接访问这些数据做一些事情了(例如根据这些数据动态创建控件)。在Load之后,如果确实有动态创建了控件,那么第二次LoadPostData就会被调用,用于为这些动态创建的控件加载数据,如果在上一次页面生命周期这些控件也有被动态创建,那么此时它们的数据就得以加载到本次页面生命周期的对应控件实例。再之后就是控件事件阶段了,所有控件都根据自己加载回来的数据判断是否要引发什么事件。

动态创建控件的最迟不能晚于第二次LoadPostData,否则创建的控件在下一个生命周期就算再次创建同样的控件也不能成功加载数据,这就确定了动态创建控件不能放到控件事件中进行,因为控件事件发生在LoadPostData后。(理论上页面生命周期可以设计为递归型的,也就是每次引发控件事件后再检查是否有添加新控件,有的话再LoadPostData,LoadPostData后再检查这些控件是否需要引发事件,不过实际上页面生命周期没有这样设计。)基本上动态创建控件必须在Load前后完成,例如开发复合控件或者模板控件时常在CreateChildControls和DataBinding中做此项工作。

如果涉及复杂的控件创建,这些控件创建必须依赖于事件改怎么办?这就只有一个办法,把动态创建变成创建所有并动态隐藏。例如制作一个有很复杂规则的调查问卷,根据答题者不同的选择转跳来转跳去(这时候你可能首先会想到ASP.NET 2.0的Wizard控件或者CrossPagePostBack,但这样每次仅显示当前的一个问题),先在页面上创建所有题目并且在Load时根据当前答题情况隐藏不应该出现的问题就是一个解决方案。这里隐藏的关键,就在于隐藏的控件不呈现到HTML上(或呈现到HTML但隐藏),但它们的ViewState却照样保存,这就使得所有的题目实际上都能够跨越页面生命周期而存在并且实现数据持久。

不过Page级别的隐藏方法好像不那么美观,所以我们应该这些逻辑封装到一个WebControl里。既然封装到WebControl里,也就没必要让各个隐藏状态的控件自行保存ViewState,直接把它们的属性统一集中到父控件并保存到其ViewState就行了。此时所有子控件的数据加载变成了由父控件统一控制,当一个子控件不需要出现时就不再需要先创建再隐藏而根本就不用创建,因为父WebControl会继续负责此子控件数据的持久。

其实ASP.NET 2.0的Wizard可能也是用类似的方式实现。在ASP.NET 1.1时我就提出过Wizard,觉得这是一个非常容易实现的控件(就按照上面的父控件统一实现子控件数据持久的方法),而且也很有价值,就是奇怪为什么各大WebControl开发商不做一个出来,结果到ASP.NET 2.0官方就做了一个出来了。至于CrossPagePostBack,用的也就是没有控件但ViewState保留的做法,每次CrossPagePostBack都把PreviousPage的整个ViewState保留下来,不过唯一问题就是如果连续用很多个CrossPagePostBack实现一个Wizard那么多个ViewState堆叠下来占用的传输带宽也一定不少。

所以说,在ASP.NET里面用好ViewState很关键(这个下次详细说),如果还是没ViewState的思想,还是按照其它动态页面语言的思路去做,那是用不好ASP.NET的控件模型的。

2006年3月31日星期五

Cassini其实不是新东西,早在2000年就有离线ASP宿主

详细可以参考这两篇文章:
http://msdn.microsoft.com/msdnmag/issues/0900/cutting/default.aspx
http://msdn.microsoft.com/msdnmag/issues/1000/cutting/default.aspx

那时候,设计的目标是为了做Demo CD,而作为Demo CD不能够要求客户机上必须装有IIS,所以就需要设计一个轻量级的离线的ASP Host。在2000年,这两篇文章归到Cutting Edge去了,不过这样的技术在当时来说确实非常Cutting Edge了,一般Demo CD最多内附一个PWS(Personal Web Server)让Win9x也能装上看看ASP的效果,基本上没有人会想到要实现自己的ASP Host。这不仅仅是技术问题,而且还是思想问题,RIA还没有提出,用HTML或者Flash做Windows应用还是非常罕见,没有人有理由要实现一个随处可运行的展示给localhost看的Web Host。

现在Cassini来了,靠的主要是System.Web.Hosting这个namespace下面的东西。其实要实现ASP.NET Host关键就是要把Request流的内容倒入HttpWorkerRequest,之后HttpWorkerRequest配合HttpRuntime就是你所要的一切输入了,而且是完整封装好和普通ASP.NET无异的了。至于输出,Cassini同样是需要实现原本HttpResponse直接让IIS实现的功能,自行把Response流的各种Header写入,然后写Response流的主体。

System.Web.Hosting其实是ASP.NET 1.x就有的东西,看来MS一早就准备了要让ASP.NET可以脱离IIS运行。如果非Windows平台上的.NET Framework能够弄出来,就能够轻易地把ASP.NET迁移过去。现在也有人在搞.NET Compact Framework上的ASP.NET Hosting(因为.NET CF没有System.Web.Hosting),那么ASP.NET就能够成为全平台的Web应用了哦,既能在线也能离线。

Macro CSS, CSS Script or Xml CSS?

继续上次那篇Programmable CSS,我现在有三个实现方案:

1.Macro CSS

用Macro来实现简单的CSS编程,既然CSS是纯文本输出,那么可以考虑仿照ASM/C++的Macro那样,定义一些简单的文本输出Macro,例如Coo所谓的自定义颜色常量就完全可以好像C++定义常量那样定义。页面就引用一个.mcss文件,这个后缀在服务器端关联一个HttpHandler(假设在.NET环境,其他语言环境自行变通),专门负责处理.mcss文件里面的Macro输出标准css。

这样做需要对Macro CSS用正则表达式进行分析,提取指令,还要做变量存储,我觉得这是比较麻烦的事情。例如变量存储,我上次说了要实现子元素可以设定padding为父元素padding的加上1px,这就需要允许在Macro里面定义变量,然后Macro运行时这些变量是无类型的,或者说是动态类型的,要支持各种运算,烦死,简直就是要自己写一个Macro Engine。

不写Macro Engine的方法有没有?也还是有的,就是把Macro转换为对应的服务器端脚本,例如ASP.NET,然后让服务器帮你编译执行,这样会舒服很多。这和直接写个满是<% %>的CSS有什么不同?我们可以为Macro CSS编写转换到不同服务器端语言的引擎,然后同一种Macro CSS就能够运行于任意动态服务器端了。

2.CSS Script

这个东西我不确定是否可行,其实就是完全用Script实现页面CSS的操作。

CSS Script拥有类似Atlas那样的一套完整的、兼容多种浏览器的Framework,然后能够用Javascript按照类似C#的写法或者类似XML的写法那样直接操作一些Framework中的封装好的CSS对象。简而言之,这就是一个CSS版的Atlas,Atlas用于DHTML和WebService,而CSS Script则用于CSS。或许未来的Atlas将会把CSS操作也封装进去,难说呢。没看过Atlas的一定要先去看看,否则会不明白我说什么的,因为Atlas实在是太过高度封装了。

3.Xml CSS

就是直接用XML来描述一个CSS模型,然后用XSLT来生成CSS,实现起来很简单,只不过用XML来写CSS或许会让人很不习惯,因为要写多很多代码。不过如果有IDE工具支持的话,或许大家都愿意接受。

原本的CSS也是DOM的一部分,除去HTML的DOM,CSS也可以独立成DOM。能够独立成DOM自然也就能够用XML来表示。用XML来表示,就可以向这个DOM增加新的元素,例如常量、运算、条件等,而新增的这些元素都通过XSLT解释最终生成普通的CSS就行了。

2006年3月30日星期四

ASP.NET 2.0解决了Code-Behind需要控件声明同步的问题

这显然是一个非常明智而且很早就应该实现的做法,因为已经在HTML中声明为runat="server"的控件,就应该算是声明过,还要在code-behind中同步的用C#代码再声明一个同名控件显然是违反了《程序员修炼之道》中所谓的DRY(Don't Repeat Yourself)原则。

原本ASP.NET 1.x的编译模型是编译站点时先编译code-behind部分,然后得到code-behind部分的Page派生类,等到运行时再编译aspx部分此事得到code-behind部分的派生类(也就是Page的二级派生类),而一旦aspx和code-behind出现控件声明的不同步那么这个继承关系将出现问题。

ASP.NET 2.0的做法就是把aspx和code-behind都看作Page派生类的partial class,并且合成编译,而aspx中所有的控件声明都将在编译时自动转换为C#声明,这样的好处是只有一层Page派生类而且不用同步什么东西,所有东西都是仅声明一次。不过有一个问题就是,到底aspx中的声明是转换为C#的partial class再编译还是能够直接编译呢?转换为C#编译是很直接的思路,ASP.NET 2.0 的内部变化也是说原本由VS.NET 2002/2003做的声明同步工作现在交给ASP.NET Runtime了,但是这样就有一个问题,如果要开发一种新的ASP.NET语言(例如Delphi for ASP.NET 2.0),那么也就必须建立aspx到该语言的翻译,这是十分麻烦的事情。但是如果aspx和code-behind分开编译的话,这好像超出了partial class的能力范围,根据C# 2.0的规范,partial class的所有部分必须是同时编译的,不可以是增量编译的,也不可以是跨语言编译的,而aspx和code-behind都直接编译的话就需要双语言编译,也就需要增量编译。

ASP.NET 2.0还有一个很好的地方,就是部署编译,你能够把整个网站都编译了(包括aspx和code-behind)然后发布,发布目标的aspx将是一个仅引用后台类的控文件,这样性能最好而且也不用担心代码泄漏(特别是编译后的dll再混淆一下的话)。不过因为aspx部分也编译了,所以这样发布的网站发布之后就不能改动。而ASP.NET 2.0还提供另一个极端,就是完全运行时编译。以前ASP.NET 1.x如果是code-behind的话,code-behind部分就必须在VS.NET里面先编译,不过现在ASP.NET 2.0能够自动监测code-behind部分是否有改动过(甚至是/App_Code目录下的其他非UI逻辑的code),如果有就运行时编译,这对于调试来说是挺方便的,不需要每次调时前先在VS.NET里面按Ctrl+Shift+B编译。

2006年3月27日星期一

关于中学是否应该教Office应用

Jim跟我说,中学花时间去教Office,还不如教程序设计锻炼一下思维能力。不过最近Piggest却提了一些排版问题,显然不上课那些功能就在二级菜单你也不知道它原来是这样用的。

Office这件东西,有人说只有5%的功能常用,95%的功能常人用不到,所以作为一个聪明的开发商就应该把主要精力花在优化着5%常用功能的易用性上,这是非常合理的。问题是,要完成一份Document所需要的成本是全局的,假如5%常用功能的使用成本很低,但是偏偏你要用到几个5%以外的功能而它们的使用成本非常高,那么无论MS如何优化那5%的功能对此都毫无帮助。例如,很可能你不知道插入分页符,然后通过手动插入回车来实现分页,结果你用20min输入完文章,然后花了10min来分页,但之后你每次改动文档时需要手动调整分页的时间和输入改动的时间是1:1,那么显然输入和分页所花费的时间将趋于1:1,即使输入部分(作为常用功能)优化得很好你做得很快,最终生成Document的成本还是被分页而卡得很高。

降低你用非5%常用功能时的成本,唯一途径就是你接受过比较系统的学习。就好像Piggest去上Maya培训那样,就好像我说学Javascript要必须看O'Reilly的《Javascript权威指南》一样,不经过系统学习那些非常用功能你是不会知道的,这时候那些非常用功能你就只能用常用功能去“模拟”,这时候使用非常用功能的成本就会暴增。很多东西称之为“易学难精”正是因为非常用功能自己学难以了解到,甚至系统教材也没有,只有长期钻研的高手才对该领域有所了解,例如ASP.NET的页面生存周期的细节,MS不肯公开细节,于是就出现了个高手自己用Reflector看ASP.NET源代码和自己做实验然后把结果公布到自己的Blog的现象。

2006年3月23日星期四

Client 说她的瘦身计划不能变,所以 Server 你必须再胖些

上次说到“HTML + AJAX + WebService = C/S or B/S?”,我说通过WebService方式调用会不会又让B/S变得类似C/S了,不过结果是Client说她不能再胖,胖了Browser就不让进,呵呵……

首先第一件事就是关于DOM,有人说这才是AJAX的本质而XMLHttpRequest只是一个小工具,不过这个本质(不是McDull的那个本质,咔咔)的执行效率就实在不怎么样,不至于很差,但是你绝对不能把以前用ThickClient的Native Code所做的东西完全交给它,因为太多了你就会发现它忙不过来。

举个CSDN上见到过几次的一个例子,就是做一个类似Google Suggest那样的有筛选功能的ComboBox,遇到问题的人都说那东西只要待筛选项超过5K就没效率了,然后我说不要用DOM来构建下拉的内容而改用拼接HTML同时只有当用户超过500ms没按键时才筛选,结果有所改善,不过可能也无法处理超过10K的待筛选项。

我自己也做过一个动态生成table的东西,用DOM构建table的话一个50*30格的就要300ms~500ms,这个效率实在太低啦。

第二个问题就是复杂的客户端调用规则。例如我有一个用户注册表单要调用服务器端的3个WebMethod:
bool IsUsernameDuplicated(string Username) //用户名是否已被使用
bool IsEmailDuplicated(string Email) //Email是否已被使用
void SignUp(...) //把所有注册信息提交到数据库

现在要求异步调用IsUsernameDuplicated和IsEmailDuplicated,我也不知道哪个先返回,但必须两个都返回false才调用SignUp,任何一个返回true或者Timeout了都不调用SignUp。这样事情就会变得很麻烦,前两个WebMethod返回时必须作标记,然后用一个定式执行的程序不停的检查这两个标记直到都有返回(或者Timeout)为止。

当客户端有一系列复杂的调用规则时,问题就更加复杂了,所以最后你会发现还是不要在客户端搞复杂调用好,这些规则应该都交给服务器端处理,然后封装为一个WebMethod。例如应该只设置一个SignUp,调用时通过返回一个int来表示用户名/Email是否已被使用,又或者用Atlas的Exception机制来返回这个。

简而言之,Client跑Browser的Scripting跑道上时别给太多或者太复杂的东西它干,它根本干不来,事情还是尽量让Server包办好了。不过也有例外的时候,例如那边Flash就在大喊我很Rich(因为它自己叫自己RIA),我可以负责很重的UI任务,呵呵……

2006年3月21日星期二

Benny说不要太早走出社会喔~

上次回去修华附论坛那台服务器时,Benny说第二天就要面试20个本科生,从中要两个,试用期月薪¥1K+,转正后再加¥500。然后我问他招那两个人的工作范围是什么,他说一个负责发布新闻,长期坐在网络中心,另外一个跟吴老师东奔西跑(估计是维修类的)。

Benny的意思就是,能够留在学校里,最好就一直留在学校里不要出来。不过留在学校里虽然什么都好,但是现在好的学校都越来越“敛财”了,所谓教育产业化搞到学校也变成了服务运营商,能够骗到一点钱就骗一点,积累资金“扩大生产”,真正专心搞教学或者研究的人又剩下多少呢?

2006年3月19日星期日

Site moved~

由于sitesled已经有一段时间无法进行FTP上传了,所以改到5000megs,PURL保持不变:
http://purl.oclc.org/NET/cathsfz

由于原来用开GB2312发布,现在服务器的charset为UTF-8,改过来可真不容易。用GB2312发布,则客户端打开时自动根据HTTP的charset而不是HTML的charset设置为UTF-8,用户需要手动改回GB2312才能正常浏览;用UTF-8发布,根本就是乱麻,因为Blogger保存文章和模板时就有charset属性,GB2312的文章按UTF-8发布无论如何都是乱码。

最后我意外找到了解决方案,就是先用GB2312完整发布一次,然后改用UTF-8发布,并把模版和首页上的几篇文章改为UTF-8,最后仅发布索引一次,那就OK了。这个解决方案首先解决了首页显示问题(这是我原本的目标),后来发现打开内页竟然GB2312又能自动识别(难道仅访问/时HTTP协议会返回charset),所以暂时我的Blog“看起来”完全没问题。

2006年3月5日星期日

My Life Rate~

This Is My Life, Rated
Life:
5.6
Mind:
6.2
Body:
5.5
Spirit:
6.3
Friends/Family:
5.9
Love:
1.5
Finance:
5.5
Take the Rate My Life Quiz

2006年2月27日星期一

Unique Part vs Replaceable Part (Part1)

某些统计数据说平均一个大学生把大学里的时间的一半甚至更多花在英语考试上(可能计算上出国原因而要应试的人吧),然后我们上学期那个英语老师又整天在提应试的事情,烦死我了,所以我就在英语作文上狠狠地讽刺了一番拿着一堆人有你也有的"证书"是很难找到工作的,只有你保证你自己的Unique的你才容易让别人招你??特别是那个职位非常适合你的时候,因为你是Unique的所以只能选你,你的开价就能够高。

讲得简单点啊,中大现在单省一它也不一定愿意保送了,要国家奖、双省一或者单省一的前20名,还要参加它的"资格考试",这就是什么东西有的人多了就难以通过它区分人的水平高低,这东西也就贬值了。所以,要么你就拿一个非常Top的证书,要确保足够少人有的那种;要么你就拿几个一般人只能拿一个的证书,证明你可以一个顶几个。

其实很老实说一句,如果你毕业之后出去做Manager,有机会给你招本科毕业生,你会不会觉得很头痛?我觉得会,因为读过的人都知道本科生是读什么的,本科生就只能证明你在高考前还是个不错的人,高考后鬼知道你干什么去了。大学就是一个拉平补齐的地方,不管你原来有多厉害,很容易就被人钝化为一模一样的Replaceable Part,然后出来就是等别人不是很行的时候就上去把别人Replace掉,之后自己不是很行的时候就又给人Replace掉。

接着肯定有人说有问题,嗯……那就先说吧,然后慢慢等Part2吧。

2006年2月23日星期四

SmartClient应该是PDA/SP上PIM软件的发展方向

Yahoo推出了个Yahoo Go Mobile的软件,能够让你直接在手机中访问Yahoo的Mail、Calendar、Weather、Messenger等主要服务,其实这已经相当于把Contact、Appointment无线化,把主要数据存储在服务器中。

Yahoo Go Mobile能否取代手机内置的Contact和Appointment暂时不知道,但这应该是一种趋势。我之前曾经说过网上的Contact、Appointment、Todo、Memo我不用,是因为他们无法和我的PDA同步,不过如果能够同步的话那就会考虑用了。对于这类服务来说,长期挂线当然不可能,难道有来电了软件需要先通过GPRS查询一下线上的Contact表然后才能显示该号码对应的联系人名称,这显然不行,所以就必须在手机内缓存一份离线数据,其实这也就是SmartClient的主要思想??两份数据、智能无缝同步。

其实真正的难度就在于智能与无缝这两个词上,不同软件的特性不同,所以暂时还没有人做出一个SmartClient的Framework出来能够兼容各种软件的数据特性。智能要求就是它懂得什么时候可以同步(例如自动在带宽闲时同步)、优先同步什么数据(例如优先同步可能将要显示的数据和关键数据)、同步对显示的影响(例如哪些数据不同步也能显示给用户看、哪些数据不同步就应该告诉用户数据已过期)。无缝则要求不打扰用户并为用户节省时间,也就是什么都放到后台自动处理掉,好像AJAX那样,用户在前台不需要浪费时间,我个人认为以后所有网络软件/服务都将向无缝发展,包括需要下载才能运行的东西,因为用户一般不会介意去点击一下“允许”按钮,只要在软件/服务真正可用之前的那段时间他可以去干其他事情而不用坐在下载进度调和安装程序面前白等就行,当然也不要过一段时间点一下是否之类的选项。

其实,很难说下一版的SQL Server Mobile Edition会不会内置和SQL Server Standard Edtion智能无缝同步的功能,因为MS竟然把js封装成.NET语法形式(也就是Atlas)这样的事情也做得出,它真的要封装一个SmartClient Framework也不是不行,然后提供一个足够丰富的config文件格式和一个类库给你静态/动态的去配置同步细节。但正如MS一贯的风格,1.0的东西都让人很期待但很不好用,2.0才有点出色,3.0才能够腾飞,所以就算由下一代SQL Server开始有这个功能,普及SmartClient这样的事情也不可能是MS做的了(因为它效率太低了),反而可能使Yahoo或者Google做了。

2006年2月18日星期六

开学了,继续忙

赚钱的项目、社团、学业……都还有很多tasks要做,有部分可以随便应付的,但是我自己想认真对待的tasks将耗费我不少时间。

不过暂时来说最麻烦的就是我有写不完的Blog,很多很多东西存在Draft中,可能因为我一早就养成了写东西写一半然后不想下去的习惯,所以很多东西都收不了尾只能放在Draft中,直到一些我有办法结尾或者我认为过期该删掉了。这是个很严重的问题,不过不是每篇文章都可能有结尾的,很多事情仅仅是有个开头的想法,然后懒得想下去,所以我决定继续按照我以前在别处的做法,就是在文章写到一半的时候不想写就写一个“待续”,然后续不续就看我有没有思路了。

2006年2月15日星期三

纯javascript和汇编越来越像了

首先先说说类似之处:

1.指令都是执行很琐碎的功能,用起来比较吃力。别以为javascript是解释执行的高级语言就好,要获取一个HTML对象还要document.getElementById(),这一情形和用汇编的mov和add差不多??看起来是非常必需的指令,但往往自然语言的一个语义(例如c = a + b)必需翻译成几条这样的基础指令。

2.指令集版本多,而且由商业因素变化而变化,不存在必然的兼容。就好象不同CPU支持的指令集一样,javascript也是这样,你想写一个兼容多几种浏览的javascript那个调试难度就大咯,有些情况下几乎你要为每种浏览器写一次代码,测试也是要分开测试,这和写兼容多种CPU指令集的软件一样。现在有专门为某种硬件优化的编译器,例如你今天可以看到游戏有Run Greats on Pentium4 HyperThreading的欢迎屏,迟点就可能可以看到有网站写着Better Visual Effects on Windows Vista with Internet Explorer 7(IE7 for Vista可能就像IE6 for XP那样是和通用版不同的,鬼知道它会不会对Vista的Theme和DirectX10有没有什么特别支持)。

然后就是我们现在面临的情景:各种各样的Web UI Library出现,这些UI Library和当年的微软的MASM有什么不同?(我个人认为MASM这个缩写中第一个"M"指Macro,如果按现在的叫法应该是MS-MASM,也就是Microsoft Macro Assembler,在MSDN你仍然可以查到MASM的帮助,不过只有关于Macro的,没有关于普通汇编指令的,可见它强调Macro的程度)。我们现在用$()代替document.getElementById(),简直就是一种Macro,我们通过Macro特别是好象MASM那样的高度自动化和智能的Macro省下了很多指令,它能够自动适应环境产生代码甚至根据复杂的逻辑产生代码,但实际上Macro离真正的可编译高级语言还有很远的距离。

什么时候才是javascript好象汇编那样,出现一种能编译的高级语言?我之前说过,有一天可能只需要写服务器端代码,就能够自动把部分生成为javascript在客户端执行,可能那才是javascript全自动生成的时代,我们离这个时代可能还有几年的距离,也可能几年没过完javascript就成为过时的技术而被新的技术取代掉。

2006年2月13日星期一

ASP.NET 2.0 ClientScript Callback

当AJAX出名的时候,ASP.NET 2.0已经基本上完成并且离最后发布时间还剩下半年,此时人人都希望MS为ASP.NET 2.0加上AJAX支持但MS说我们没时间加了,AJAX将成为独立的Atlas项目并出现在ASP.NET 3.0中。不过ASP.NET 2.0中有一个非常通用的但只能称为Method而不能称为Framework的AJAX支持,那就是Callback。

Callback的使用非常简单,首先你要有一个实现了ICallbackEventHandler的Control,例如你在你的Page上面实现ICallbackEventHandler,这个接口会要你实现RaiseCallbackEvent()和GetCallbackResult(),讲简单点其实它们就从客户端接受一个String的传入交给你处理,你处理完就传回一个String给客户端,详细的处理由Page的RenderCallback来负责,这个不需要你操心。

如果你用Callback,好处是你不需要管什么WebService之类的东西,你可以把Callback整合到Page里面(如果你一个Page只需要一个Callback)或者你自己封装的某个Control里面(如果这个Control自己使用一个Callback)。可以看到,Callback是希望你把处理封装到Control,例如你自己可以继承Button写一个CallbackButton实现ICallbackEventHandler及其两个函数,然后你把RaiseCallbackEvent()冒泡为CallbackClick()事件。

Callback有一个有趣的地方,就是传入和传出String分在两个函数里面了。看起来,这是很蠢的行为,但实际上它是为了符合ASP.NET对象模型那种事件处理方式,也就是Event与Render的分离。ASP.NET里面,Event和Render不像ASP那样是直接相关的(因为某个按钮点击了,所以输出某个反馈),Event是影响于ASP.NET对象模型,或者直接点说主要就是控件树和HttpContext,然后Render是根据控件树和HttpContext去生成HTML,但任意多个Event对控件树和HttpContext的影响应该是正交设计的。你可以在Callback的时候好象Postback那样把所有数据都发回来然后填充控件树然后Render时就如Postback一样根据整个完整的控件树去输出。

最后,Callback是一个半成品,MSDN中关于Callback的资料也有很多错漏的地方,所以大家自己弄清楚怎么用好用就够了,MS的目标是让Callback和Postback一致从而方便实现AJAX,但暂时还没有实现,还有很多Script代码要自己去写。另外我在看Callback的文章时看到,在System.Web.Util里面有很多很好用的小工具式代码,可以给你带来不少方便的,在你写例如服务器端String转换为脚本端String之类的代码前请记得找找那里有没有写好的,不要为此而浪费自己的时间。

2006年2月12日星期日

Programmers Eliminate Programmers

开发自动化工具的程序员总是在不停的"消灭"其他程序员,至少在不断让别的程序员的劳动甚至是创意贬值,呵呵……这是一场很有趣的Race,就是你每天在不停的写程序的时候,其实你也就在让很多别人写的代码甚至你自己以前写的代码变成垃圾,因为"可复用(Reusable)"真的是一种很可怕的东西。

物质产品方面,重来没有什么Reusable可言,这就是经典的"价值"与"使用价值"只能取其一理论。只有IP(Intellectual Property,知识财产、知识产权)才可能reuse,这个reuse就是指在不付出价值的情况下,你可以直接得到使用价值。于是,一旦有人做了的东西,它就可以被reuse,其它人也就不需要做了,做了一半的也没用了(这让人想起Civilization里面的奇迹建造,任何奇迹第一个造出来的文明能够获取此奇迹,其余文明就算做到一半也没用)。这时候,作为程序员,最坏的情况不再是不做,而是做了一半然后别人先做出来了,这样的损失比不做还要大,哎……

所以,程序员不仅仅要去工作,还要选择对的来做,否则就很容易给别人干掉。说得好听点就是享受别人的工作成果就是了,但实际上就是自己实现不了任何的价值。

暂时我觉得最好的全能索引方式还是Google Base

所谓"全能索引",就是不仅仅像"全文索引"那样增强对文字(例如时态、人称、单复数变化)的索引能力,而是对任意事物任意属性的索引方式。

因为是任意事物任意属性,所以数据表没办法表示好这种东西,必须使用XML那样的方式。Google Base能够做到,因为它不仅仅允许你好像XML那样发布一个事物及登记其属性,更重要的是它能够对类别与属性的名称进行感知,避免滥用(Abuse)。

首先是发布时输入的类型,虽然不仅可以从已有的热门类别选择还可以任你填,但你别以为真的好像普通的tag系统那样任你填哦,你填一个不是单词的上去看看,或者填一个非名词进去看看,你就会发现Google Base提示错误。至于它怎样做到的?因为它基于现在所拥有的数据库,已经能够懂得什么词能够表示一个类别。同时,我也怀疑这个类别它已经知道同义词的存在并且能够同义词归类,例如Blog、Blogs、Blogger、Bloggers等它应该都知道是同一个东西。在输入类别之后,它就能够进入登记属性页,这时候它又能够自动出现一些此类别对象常见的属性,这个我暂时不确定是它根据其他人登记时创建的属性总结出来的,还是即使你创建一个没人登记过的类别的事物它也能列出若干建议属性来。

在属性输入页,你可以删除已有的建议属性或者添加新的属性,这就是类似XML的地方,这些属性也是有类型的,这样就算是同类的事物不同人创建的登记的属性的详细程度也就不同。这时对于之后搜索很好玩的地方,在搜索的时候它懂得提示你按照某个属性来缩窄搜索范围优化搜索,例如People并非每个都有登记Age,到底是否该提示你通过Age范围段索债搜索范围呢,这也是一个职能的地方。

如果我知道如何写数据库引擎,我也写一个轻量级的Google Base来玩玩,据说Google内部有一种BigTable的半结构数据分布式存储和访问接口,这个是从Dash的Feed看来的,原文在这里:
http://www.wespoke.com/archives/001042.html

其实说起这个,是因为我想来想去都不知道那个协作系统如何发布idea,这真的是一个很头痛的问题。idea,就好像我上面说的那样,有任意多的属性,而不仅仅是通过tag就能解决的,我需要一个办法把它们索引起来。而且,你单作一个这样的系统,别人还未必愿意到你那里登记。反而好像Google Base那样,既不说交友信息招贴栏,也不说出租房子招贴栏,但贴的人就不少,有一天Google突然宣布Google Base该怎么用好了而这时它已经有了大量的数据作为启动基础。

2006年2月8日星期三

卖服务还是卖产品

最近又见到有人讨论,最一种很通用的Portal好不好,就是那种可以直接在Web界面上设计数据库,生成WebForm,设计业务逻辑那种。简单来说,就是一个比Sharepoint更容易直接在Web上灵活定制的东西(Sharepoint的Web定制能力一般,要定制还是要靠继承原有类编写新代码),整一个Web版Access甚至Sql Server那样。

我第一次见到Sharepoint Portal Server 2003时,就有这个想法,当时就觉得它是一个Sql Server to Web,只不过Web定制能力不强。当时对ASP.NET的底层了解不多,不敢去详细想如果做一个更好的有多难。现在觉得不难了,不过倒觉得做这样一个东西拿去卖实在不容易。虽然想想,如果作为一个小站长,不需要懂太多的技术知识,也不用在客户端装Frontpage、Access、Sql Server 企业管理器之类的,打开网站就能够直接在IE里面编辑HTML,设计数据表,然后设计事务逻辑,多爽。然而,还必须关注一个问题是,现在的小站长去哪找一个空间支持你这套系统?人家可能自己设计HTML不怎么好看,但找一个免费的静态空间比起找一个支持这套系统的动态空间可要容易不少哦,可能人家的HTML设计出来才几M甚至几百K,而如果用这套系统他就要去找一个50M的动态空间先把这套系统Upload上去,显然很不划算。这样说来,卖产品还不如自己做Host然后直接提供这样一种服务,客户买空间的同时也就得到了这套系统的使用(实际上用这套系统的人,都不会想获得它的代码)。

其实现在我们看到的情况就是,Web 2.0,Longtail,越来越多普通的End-User加入到其中来,不再是Professional User单向发布的时代,我们需要满足很多自己没有能力Host自己的东西,所以我们必须改掉老一代Web开发者那种制作一个Web站点然后让别人自己host自己用的想法,而是直接提供一个host这种服务的平台让客户可以直接使用。

不过这种趋势实际上就是提高了开发者的门槛,小开发者往往不能自做host,SP之名就更加高攀不起,只能考虑作产品然后卖掉。可是现在“卖掉”这条路不好走咯,那就只有考虑Open Source,看看哪家有能力作host的看中,然后整个拿过去作为合作项目,那样才有可能收到钱。说到Open Source,其实这在国外还算是一条赚钱的方法,不容易找到客户卖掉的就不如Open Source,这样反而更多人关注更容易找到合作机会。当然,国内是另外一回事,无论是创意还是源代码都是可以抄的,对人和知识都没有任何尊重可言,任何东西公开之前还是改深思熟虑。

回归原来的主题,既然潮流正在改变,如果能够抓住这个机会,出一两个主打的服务,至少算是和时代同步,如果继续做“可能能够按copy卖掉的站点”,那就肯定卖不掉咯,今时今日不能copy确保unique的东西才好卖。

是游戏还是感官刺激?

刚刚开始有电子游戏的时候,还是非常之"游戏"的。这里的"游戏",也就是所谓的Game,翻译成"博弈"也没错,总之你就是有一个竞争对手,而你的目标也就是赢它。

游戏的拟真程度本身是一种游戏性的需求,看起来一样游戏方式的游戏,有一个绿色色块表示一个人还使用一个Logo表示人,玩起来后者的感觉显然比前者好。因此,游戏的拟真程度的发展,以及它推动着相关技术的发展,是很自然的事。接下来的事情,就是拟真度不断提高,然后就会有人就发现了“过度拟真”的好处??虽然看起来有点假,但你可以说那叫做艺术,最重要的就是玩家喜欢,因为大部分玩家一定程度上都是个“感觉者”(“感觉者”的定义来自D&D中Planescape背景设定),也就是喜欢去感受一些没有感受过感觉,特别是比较激烈的感觉。

于是有些游戏开发者完全是去讨好玩家的感官刺激需求,同时游戏的感官刺激就有点如drugs,一旦上瘾就放不下(例如现在叫你用17寸屏玩320*240的游戏,你绝对不会玩,你只会说如果能够用PPC玩的话那还不错),而且只有刺激越来越大才能有感觉。这种现象,就是部分玩家所谓的某某游戏让某某类型游戏死亡,例如最近有人说《神秘岛5》让解密游戏死亡,因为它本身不是超级解密游戏但就靠画面强,而如果出来一个游戏性好但画面无法超越它的解密游戏玩家可能又不愿意玩。

然而,实际上技术进步所带来的最终还是应该应用到游戏性上,而感官刺激是次要的。只有有新的游戏特性,那样才能吸引玩家,因为这个“新”是可以无限创新的。而感官刺激是一个一维量,你要增加这个量,总会面临技术所带来的极限,但游戏特性的创新则不会。好的游戏懂得利用技术在游戏性和感官刺激方面同时提升,如果游戏开发者仅仅注重人在某一方面感官上的刺激,那么游戏就真的很容易变成Drugs,因为人是基于本能的去“简单”的追求单方面刺激的提升。

2006年2月6日星期一

从亚健康到不健康

最近常常工作、看电影或者各种原因弄到三四点才睡,幸运的也两点才睡,发现Health程度爆降,然后Strength跟着跌(Max HP也会跌),所以决定从今天起,一定要早睡早起(先试着零点睡觉,这已经算早的啦)。

本猫是非常依赖于睡觉和享受睡觉的,没得睡觉会死猫的,无论采用正常作息时间还是滚动作息时间,都一定要睡够,那样工作的时候才能高效率输出,否则慢慢挨更加累死猫。

2006年1月30日星期一

The Redesign of Cat's Personal Indentity

"Cat"这个名称的使用率太高啦,别人不容易搜索到,这样比较麻烦。同时有时候要提供Unique Name的时候,也就只能用"cat_hsfz"或者"cathsfz"取代,很麻烦,要提供Logo/Photo时也没有。

现在决定重新设计整个Personal Indentity,包括Name和Logo,这要一段时间。Name的话,我准备改为"Cat*****",也就是在后面扩展,这样好像比较容易做过渡。然后要搜索一下,看看有什么结果,搜索是没有结果就最好了,表明这个名称是Clean的。然后再设计一个适合的Logo,就可以用于需要Logo或者需要Photo而不一定要真实Photo的地方。

大家有什么idea可以说哦!

2006年1月28日星期六

Time Fragment Management

在Social Convenience里面提到时间过于灵活时,就很容易产生随便,难于管理。这让我想起在C语言里申请内存空间时的一种策略。

这种策略就是,申请和注销内存空间时,大小总是2的n次方,如果你有点学数学的天赋,马上就能feel出这样做的好处??这样你就避免了空闲内存的大小是奇怪的数字,而让他们尽量也是2的n次方(或者至少,他们的大小的因数主要是由2组成),然后你再次申请空间时就很容易把空闲段用上了,从而减少碎片的产生。

在时间管理方面,我觉得也是类似的,虽然没有人给我们任何规则要求我们如何划分空间,你可以逃课,可以迟到5分钟叫做正常到课室上课,但实际上你最好有一种严格的分配策略来划分时间,而没必要为了节省几分钟而打破时间划分策略最后因为时间碎片而造成更大的浪费。

better plan往往就是打破时间划分策略的凶手,例如洗完衣服再去晚自习反正没人规定我多少点到。然而你想想在你中学的时候,是严格规定你几点出宿舍去自习的,你不能够说洗完衣服再去,没洗完你就只能晚自习回来再洗。看起来这样把你的戏衣服时间切割了造成了碎片,但实际上却保障了你晚自习第一节课的时间的完整性。这个完整性有什么用?例如你晚自习第一节课45min,这相当于一个contract,承诺任何小于45min的task你都可以放在里面完成,例如做一份需时40min的题目。如果你选择洗完衣服再去晚自习,那就打破了这个contract,你不能再确保40min的题目能否在剩下的时间做完。例如你洗衣服占区第一节课的8min,你就还剩下37min,为此你可能会选择课件再做3min把题目做完,但同时你也打破了课间10min的那份contract,你做完后剩下7min的课间可能难以填充什么进去。反过来,如果你保障了45min的第一节课,就算做完剩下5min浪费了,然后课间那10min你就可以另作安排,总好过浪费7min。

可能有人会说,better plan浪费7min和严格的时间划分策略浪费5min只是一种碰巧,有些情况回倒过来。没错,确实会,就好像划分内存无论如何都会有碎片,但如果你的碎片大小不是奇怪的数字,而是存在一定的数学规律(例如某个数的倍数或者次方),那么若干个相邻的碎片连在一起的的时候它的大小还是呈现出这种规律,同时你又是按照这种规律去划分,那么出现碎片的机会将减少,同时碎片浪费的比例也是一个可计算的值。但如果你没有任何contract的去用,产生的碎片及造成的浪费将难以计算。

HTML、CSS、Javascript有时间还是应该系统学习一下的

最近看了一下O'Reilly的《Javascript权威指南》,发现HTML、CSS、Javascript这些那么有“历史内涵”的东西,有时候自己靠模仿别人的代码来学只能学到一些表面的东西,呵呵……

所谓“历史内涵”就是指发展过程中因为各种因素而改来改去,要兼容这个兼容那个,还有企业为了竞争而把东西弄得不标准,等等。有复杂“历史内涵”的东西,你不系统学习,很多小东西你根本不知道,用起来就总是走弯路,例如有功能你不会用,或者用起来总是碰上浏览器不允许你这样用的地方。

以前我都是靠看Sample和MSDN学习的,不过MSDN其实也“太不中立”了,很多东西都是以MS的标准为主,虽然现在也把W3C标准的东西写到里面去了,但其时不全的,如果你以为MSDN里面的东西已经把W3C标准包含进去了,那就死定了。而且MSDN里面W3C标准的东西更新总要慢一些。

O'Reilly另外还有《HTML权威指南》和《CSS权威指南》,如果我有时间看书,一定买回来看看。不过现在自己看书的时间实在不多,常常开了电脑就不愿意看书了。嗯……一定要找个方法把自己的时间管理好。

Blogger的Template实在不爽

主要是帮助解释不清楚,搞到有时候你以为这样写Template没问题,而Parser却按照另外一种方式帮你生成HTML(可能Parser根本没想过你会这样写),哎……

做项目做得累了,上来发发Blog,嘻嘻……

2006年1月27日星期五

Social Convenience

为什么学生会那群人整天去贝岗村吃饭和劈酒,而且还挺有“等级意识”的,一开始我也不懂,不过现在逐渐发觉确实social的成分很大,而且有时候必须为了social而social。

在中学的时候,你根本不需要所谓的Social Convenience(社交便利),因为你和你的同学天天见面,所有课都一齐上,一起吃饭,一起回宿舍,一起熄灯后讲话(因为宿舍没有电脑没有QQ)。这就好像在玩Sims时一样,如果你一直在social,该项需求一直都是在高度满足状态。当时有位美院的师兄面对我很不屑于CS的态度说,你知不知道为什么大学里那么多人玩CS,这其中有一个因素就是平时同学之间交往的机会非常少,而CS正是少有的能够进行社交的一项活动。我当时对此持怀疑态度,因为打CS好像娱乐成分远比社交成分要低。

但现在,我才发觉大学生之间真的是如此缺乏日常社交。这里面有很多原因,不过我认为最直接的原因就是时间差,因为时间松动了,不再是中学那种所有人都一致的作息时间安排。可能你觉得这个时间段忙这个好,我觉得那个时间段忙那个好,而只有当两个人都是空闲的时间段才可能用于两个人之间的social,这就造成了:1.用于social的总时间减少,往往你得闲时别人不得闲,你想拉人和你一起去吃饭时别人忙于打机;social的对象难以固定,随机性大,今天可能只有A有时间和你一起去吃饭,明天可能只有B有时间和你一起去吃饭,你难以做到一群熟人总是有若干固定的时间在一起。

这个问题的出现,导致必须找时间一起social,就好像学生会那群人一样。一个人在宿舍很无聊的时候,你就会想找人陪你聊天什么的,至少陪你下楼走一趟吃点东西,不过A在打机、B在洗衣服、C在赶作业、D在洗澡……等你郁闷够了开始看电影了,可能E就来问你有没有兴趣陪他下楼买烧烤,然后你告诉他看完电影再去,于是轮到他郁闷。面对这样的问题,最直接的做法就是“合作”,也就是我们商量定一齐social,可能今晚你牺牲打机时间,明晚我牺牲做作业时间,但总算找到了一个解决方案。但是,显而易见这样的social效率显然比较低,因为总有人有所牺牲,至少“觉得是牺牲了”。

其实“牺牲”这个问题说起来就很奇怪,在你受到严紧的作息时间限制时,大家有共同的Social时间,而且你不能选择把别的事情填充到这里(例如中午一起吃饭,因为你不能选择中午上课提前吃饭),所以你不会觉得是牺牲。但是在时间很灵活掌握的情况下,和严紧作息时间对比你会有better plan(例如你确实觉得中午上课更有学习效率),这时候你就会认为放弃better plan而去social是一种牺牲了。暂时来说,我找不到在时间过度灵活的情况下如何安排social,因为这不是个人时间安排,而是要看多个人的时间安排的。

2006年1月21日星期六

花了一些时间,重新让Template符合XHTML

现在使用的是XHTML 1.0 Transtition,以为符合XHTML了就能够XMLHttpRequest获取到XML了,结果发现Parser好像还是不承认,那没办法啦,只好考虑真的输出XML了,然后我另外做一个Blogger页面。

寒假有n多的Web项目要做,看来没时间做别的事情咯,呵呵……连思考和写Blog的时间都不多了。CooWona开工了,有空要关注一下,好像是挺有价值的一个项目。

2006年1月19日星期四

Live Messenger 的共享目录其实很好用

对比传统的传输方式,利用空闲时间空闲带宽自动上传以达到同步实在很好,不用你专门去手动上传或者传给对方,不过好像没有办法看到是否已经传完。

最近买了台TX,又要找各种适合的最新的Palm软件啦,于是就和Piggest狂交换软件,用的就是Live Messenger的共享目录功能。有什么好用的软件,就扔到上面去真的很方便。

看来IM集成文件共享甚至P2P应该能够做大,反而传统P2P要加上聊天功能则用的人不多,因为不是基于真实中的好友。应用SNS的理论吧,朋友之间需求的东西重叠面往往更加广,对于P2P来说这本来就是一种优化,唯一的问题就在于两个人的上线时间可能不同,而P2P必须同时在线,如果这个问题能够得到解决,例如如何寻找好友共同在线时间,基于SNS的P2P可能比Shareaza那种Hub-Leaf模式更加有效。

2006年1月16日星期一

准备彻底改造我的Blogger Template

首先,我准备为友情链接都加上ajax方式的ping,自动按照ping排序。然而,如果每次点击进入一篇blog的comment又要切换页面,造成友情链接列表又要重新通过ping来排序,所以现在就要连打开comment也换成ajax实现。

另外昨天看到Coo的del.icio.us收集了一个如何实现同一个页面多个XMLHttpRequest请求的文章,其实用数组实现还不如封装成XmlHttpRequest Pool,就像调用数据库时的Connection Pool那样,让Pool自动管理哪一个XMLHttpRequest空闲,当没有空闲时自动创建新的,当达到Pool最大容量时就抛出错误。

2006年1月10日星期二

HTML + AJAX + WebService = C/S or B/S?

关于事物发展总是呈螺旋曲线形上升的,我总是很同意,事情发展到一定的阶段其属性又和发展之前相似了,不过本质上已经提升了一个层次。

最近我和一个做Java开发的朋友聊天,他说他在为点心做一套BOSS的系统,准备全部用WebService,然后前端WebUI通过AJAX方式调用。详细的我不说了,如果去掉JSP部分,我们考虑发展为HTML + AJAX + WebService,是不是又回到了C/S时代?我们不再需要为一个跨越两端的东西(Page,也就是View)而编程,清晰的MVC再次出现,而大量ServerScript变成清晰的WebService同时处理重点再次转移到ClientScript,这是不是ThickClient的再现?呵呵……

C/S就C/S吧,又没什么不好,或许Avalon + XAML + .NET也是这样的模型。经过B/S的进化,这样的C/S也就规定了Client只能生存在某一个普遍使用的客户端框架下,例如Web框架,或者稍微不那么普遍的Java/.NET/Flash框架下。只要基于这个框架,那么Client的移植性是不会有问题的,老C/S架构关于Client移植性的问题也就解决了。Java搞跨平台那么多年,最终最成功的跨平台客户端框架是Web;MS现在自称其SmartClient思路集C/S + B/S + RIA的优势,而去掉这三者的劣势,不过最终能够达到这一目标的可能又不是SmartClient而是别的东西。

Windows Live Messenger Beta的赚钱业务不少哦!

在MSN7里面,就已经有个叫做“动漫传情”的东西,虽然只有几个可能,但从一个“更多”的按钮就能够看出应该是能够有下载的,而下载不提供在内证明肯定是付费服务。到了MSN8,终于开始把这些收费服务推上线了。

在图释里面,有了几个大大的图释集合图标,点下去就会打开新窗口出现如下网页。一个图释集合大概有6~7个系列图释,价格为$1.5(对于美国用户来说不贵),可以通过手机或者信用卡支付。
LiveMessenger.Emoticons.Selling

然后我就顺便看看这个网站还有什么好买的东西,以下是图释集合的列表,看起来有些确实很有趣哦,不知道MSN8正式发布时会不会有中国区的价格,有的话相信不少人会愿意买的。
LiveMessenger.Emoticons.Selling.List

这个是所谓的Muggins,应该就是用与MSN头像的啦,这样看起来好像放在玻璃窗里的展示品,模模糊糊的,不比QQ Show的好看。
LiveMessenger.Muggins

但是你进入Muggins购买页之后,就会发现这个东西比QQ Show要强大得多。首先,它是全Flash的,人物身上的东西先选要哪件,再选主色调要什么,搭配好整个Look了再付钱。一个Look就$3,比起QQ Show要一件一件衣服和首饰付费还有半年就过期好得多。另外这个Flash头像还会动的呢,平时会眨眼啦,如果你输入例如":-)"的表情符号,它就会笑一笑啦。在下图这个页列出了各种表情符号,你可以去尝试预览它们对应的动态效果如何,这个可比gif贴图而成的QQ Show强多了!
LiveMessenger.Muggins.Moods

作为Live Messenger Beta的用户,我觉得MS应该送我们每人一个Muggins嘛,反正才$3,然后等MSN8正式发布之后我们这些Beta用户肯定会为了展示自己的Muggins大力推广MSN,拉其他人都过来看自己的Muggins的。

2006年1月9日星期一

世界上最大的SEO

世界上最大的SEO,不就是Google自己咯。面对GFans.org首页那句“不讨论 SEO 及相关”,有时候真的不知道该怎样想好,作为Search Engine,自己当然是自己最大的Optimizer啦。

留意在Google Account上面列举的Google Service,你能够看到Google Urchin,这个实际上就是Google Analytics。当然,我不是很明白Urchin是什么,然后就进去看看到底是什么回事,然后找到这里:
http://www.google.com/analytics/urchin_software.html

Urchin Software就是Google提供给例如Intranet的离线Analytics服务软件,而这个软件只能通过Partner Service购买。虽然这个软件还没有中文版,但我们看看在中国能否找到Partnet Service:
http://www.google.com/analytics/support_partner_provided.html

然后在中国区找到唯一一个:LexAd Advertising(http://www.lexad.cn)。进去后title大大个SEO(不知道为什么现在打开这个网站已经打不开了),原来Google的“合作伙伴”本来就是专门为客户做搜索引擎相关服务的,呵呵……

其实,SEO是个中性词。虽然Google官方网站也叫大家不要信SEO和使用SEO,否则可能受到PageRank Zero惩罚,但是Google也有合作伙伴是SEO。这个词就如“财产”,关键是是否“合法”,合法财产就受到保护,不合法的就……

通过合理分析站点数据(例如用Urchin)优化站点获得的流量提升,那就算是正当的SEO。没有那么多流量充大流量的,那就是非法的SEO。当然,事实不会是那么绝对的,现实中有很多“灰色收入”,SEO也一样,这个就算是Google也没办法准判啦,呵呵……

2006年1月8日星期日

很久没有上过“Internet”了……

90年代末上网的时候,都还可以说是Internet。虽然是拨号上网,但是接上去之后你就会发现哪里都能去,哪里都能访问,慢也是全世界一起慢。

现在情况不同咯,小区宽待或者类似的LAN接入形式不用说,先要LAN内相处好。就算是所谓的直接接入,甚至是光纤接入手头上有几个Internet IP,感觉也不过是接入了一个WAN。想要和其他WAN沟通?WAN与WAN之间速度慢是一方面,还可能有各种因素让你无法访问另外一个WAN的一些内容。

反正,不再有接入Internet那种想去哪里就去哪里的感觉,就像以前白云山鸣春谷那些小鸟一样,不是放在LAN这样的小笼子里,而是放在WAN那样的占据整个山头的大笼子里,但还是出不去哦(生殖隔离,人工选中,问你死未)。希望WAN的界限能够打破,因为鸣春谷那个大笼子都已经拆了。

2006年1月7日星期六

不太敢在Blog发表太多Idea

在中国真可谓“天下服务一大抄”,再好的Web 2.0服务或者创意,都会有人抄。本来就只是说中国人喜欢抄一些硅谷新兴网站的创意,现在中国人抄中国人的网站也有了,www.douban.com就给人抄了,实在是让人觉得抄袭者太可怕了。

本来借别人网站的服务特色融入到自己的服务中,自己的服务突出另外一种特色,这也算很正常嘛。但就是完完全全抄别人的一切,甚至连页面布局都是抄的,这实在是太没有水平了。以后还是不要发那么多东西在Blog好,内部的东西还是发到内部的Mail List,免得那么多人知道。

终于弄好了Cat's Project子站点

其实这是和Piggest商量了很久要做的事情,就是专门弄一个地方用于作品展示,把自己的作品都收集起来整理好放到这上面。

现在先把这个作品展示站点放出来:
http://cathsfz.sitesled.com/project

然后慢慢添加东西上去,把以前做过的作品能够整理出来的东西慢慢放上去,不过重点还是把以后的作品链接上去。

2006年1月4日星期三

XFN - XHTML Friends Network

刚刚发现了这个挺有趣的东西:
http://gmpg.org/xfn

它的大概作用就是,在XHTML的标准上还是用语义网的思路定义一种用于表示朋友关系语义的attribute。一般用于Blog特别是Blog中常见的链接到朋友的Blog的友情链接区域。这是一个trick,仅仅是为了将来能够理解这种语义的parser来解释,它就是在a这个tag上面加一个rel的attribute(根据XHTML 1.1,a能够有rel吗?这个要查查),然后这个rel用空格分隔的形式可以写入以下关键字:

关系:friend acquaintance contact
现实:met
专业:co-worker colleague
地理:co-resident neighbor
家庭:child parent sibling spouse kin
爱情:muse crush date sweetheart
标识:me

简单来所,你可以用一下这个页面为你生成一个你需要的有rel的a:
http://gmpg.org/xfn/creator

我主要是觉得这个思路不错,在原有的XHTML标准上,利用一些没有最小化attribute应用范围的空缺,用于自己的语义标记。只要这些语义标记不经过某些“自作聪明”的parser然后被过滤掉,那么这份XHTML就能在传递途中永久保留这些语义。在XFN的background中作者谈到,基本的设计出发点就是as simple as possible,这是一个很好的思路,别人的架构如果足够优美而又有空间放你的东西,何必自己重建?

现在所有在线Calendar和Todo做不好的地方

那就是不能够和其他服务、软件同步。特别是对于平时用Outlook/Exchange Server和PDA/手机同步的人来说,自己已经有大量的数据,不能够同步到网上的服务,为什么要去用网上的服务?

其实要做同步不难,很多大型的这类服务都采用类似IMAP的方式来存储(因为都是由做Email座过来的),都支持类似IMAP接口的查询,至少Outlook/Exchange都是。但到现在为止,除了当初MSN Premium用户能够享受Outlook Connector同步以外,我还真的没见过哪个网站能够同步(Sharepoint的不是同步,Sharepoint是在Outlook里面添加一个新的、使用在线数据的Outlook Folder)。

现在要做这个应该已经不难,特别是对于ASP.NET来说。Windows Mobile 5.0的Outlook和Outlook2003都有很好的.NET编程支持,一个Session.*List就能够把整个联系人列表或者约会列表的枚举弄到手,接下来同步的事情还不容易?假如我要做这样的服务,肯定会考虑对Windows Mobile 5.0和Outlook2003提供同步支持,甚至高级同步支持。所谓的高级同步支持,就是要像Web 2.0的操作那样,没有明显的操作延迟(同步那个时间很长啊),尽量不打扰用户、不需要用户显示操作或者回应某些问题,能够自动根据网络环境优化操作。

2006年1月2日星期一

SNS的两个业务重点

1.Personalization,也就是个性化。这是很多SNS发展起来必须要做的东西,例如提供Blog、Podcast服务啦,提供个性化主页(也就是不允许你设计HTML但是允许用它提供的组建简单设计,例如MSN Space)。为什么要允许个性化?这是个很严重的问题,因为SNS甚至Web 2.0的重点就是人人参与,人人有股份,所有人人都要推销自己那一部分顺带就推销了整个整体(上次任敏跟我说这东西现在有个名字,叫做“??公关”,“??”是什么她也忘记了)。

有一句话,叫做Every one would be famous for 15 seconds(人一生中总有15秒钟的辉煌),或者叫做15 seconds of fame。而做Blog/Podcast的,有人说甚至包括参加超女的,都是为了这15 seconds of fame??赢了就是一辈子的fame,输了也算体现了15秒的。

所以允许个性化,允许张扬个性很重要,这是任何一个Web 2.0项目成功的关键。不要强迫用户行为符合某些“业务逻辑标准”,最好他们什么都能做,无论做什么都能体现个性:Blog发表是一种自由的方式,自定义门户页是一种自由的方式,tag则是我认为至今为止最自由最突破业务逻辑限制的方式,至少在Web上是。我们期待Web上能够看到好像Lionhead Studio的Black & White甚至是The Movie那样高自由度游戏的使用方式(详细可以看我那篇《关于模拟游戏和Spore》中关于Game plays men的部分)。

2.Social Network,这就是SNS本身的业务,而其重点我认为是Karma和Testimonial/Review。Karma直接翻译就是佛教的“因果报应”,也就是你现在所做的事情将影响到你将来的命运。例如你曾经如何对别人,那么在Social Network上就会反应过来别人对你的Rating和Review如何,而且这些Rating和Review是“不可拒绝”和“相对匿名”的。(“不可拒绝”指的是在现实中有人要在你背后说你坏话,你是绝对阻止不了的。“相对匿名”指的是发表对你看法的人在他的人际圈中可以是实名发表,但对你来说这个影响源头是匿名的、不可知的。)

例如Orkut,我认为最好的一个SNS,当初能够赢Friendster我觉得仅仅就是因为它加上了Karma和Testimonial这样好玩的小功能。至于iKarma,这样一个为了Karma和Review而存在的SNS,属于纯商业性关系型的SNS所以不做个性化部分,能否单纯靠Karma服务而存活,暂时还很难说。

Karma一个有趣的地方就是,我允许你个性化,你做什么都可以,我不从系统层面或者管理员层面给你设置任何游戏规则,真正的游戏规则是好像社会道德那样来自每一个人对你的看法而造成的约束。如果一个论坛,不是通过论坛过滤禁用词,也不是通过管理员惩罚使用禁用词的用户,而是通过Karma这样的方式来提高使用禁用词的代价,那么每一个人都会明白发表禁用字不仅仅是系统会拦截或者管理员会不爽,每个用户都会对我不爽,那我还是不要发好了。

R3Y设计里面基于发送者的贝叶斯统计和垃圾过滤也是基于类似的思想,我不会说因为机器根据统计觉得你的是Spam就是Spam。而仅仅当你的朋友觉得你的消息是Spam时我才帮助他阻止你的信息;但是如果有另外一位朋友觉得你的不是Spam还非常乐意为你转发,那么你的消息还是能够畅通的发送给那位朋友。然而总的来说,决定你发送的消息是否为Spam的不是系统,而是其它人,这比起Google所谓的“系统结果决定一起,不参入任何手工结果”更加进一步。

2005年12月31日星期六

ASP.NET 2.0 实在太强了!

.NET Framework 1.x设计很优秀,但是很多东西都还没有,只能借用.NET Framework写自己的Framework然后再用。好象.NET Framework给你不少东西,但实际上你自己不开发自己的Framework那么.NET Framework根本做不了大项目。例如Sharepoint的WebPart架构是套很好的东西,但是只有MS自己用得爽,不装Sharepoint你就不能用。

不过ASP.NET 2.0则好很多,它吸收了不少1.x上面MS或者第三方Framework的东西,然后都放到2.0里面去了。例如WebPart现在可以直接用了,虽然背后的东西和Sharepoint的是不同的,但在现实效果上已经和Sharepoint的无异;DNN的Provider的设计思想也用上了,所有后台的东西都通过相关的Provider进行连接。

现在用ASP.NET 2.0开发,真的是基本上不用设计者花时间在设计用户数据库与用户类的封装、门户页面的可拖动元素Script之类的事情上,这些麻烦的事情都能够用系统的来完成(除非你有很特殊的要求,系统功能已经有比较良好的扩展性)。那么用ASP.NET 2.0开发就真的进入了比创意的阶段了——你不能再说别人懂做可拖放门户页或者别人的用户数据库设计得好,然后你做不到,所以你的好创意无法吸引客户。这也让进入Web 2.0的竞争更加激烈,因为技术已经变得简单,只有好的创意才能够吸引更多用户,否则再有技术也无法在ASP.NET 2.0中给你那么大一堆服务器中突围而出。

2005年12月25日星期日

只许邀请不许注册——确保用户是你忠实Fans的有效方法

Orkut是这种方法的首先探索者,当然它后来遇到了所有SNS现在都遇到的问题,那就是一个人进入SNS必然经历的三个流程:被邀请、邀请别人、不再使用。这让SNS的用户使用量看起来有点像只有一个波峰的机械波,不断向外扩散,但是所有人经历了一次波峰后就不再活跃了。对于这种现象我暂时无法解释,我的建议只是绝对不要做单纯的SNS,一定要配合上用户会长期使用的功能。

Gmail是第二个这样的产品,不过它很成功。对于想要Gmail的人来说,开头能够弄到一个Gmail实在不容易,所以会把它看作很有价值的东西。到现在Gmail泛滥了,但是如果你是被邀请用Gmail的,你肯定会经历被邀请者极力说服你用Gmail这一过程(例如你会说“我现在的163.com也有2G而且用起来不错”),而且如果最终你接受了邀请,那种明在例如Gmail好还是163.com好的这场论战中你的朋友(极可能是一位GFans)赢了,然后你使用上了Gmail,还被慢慢同化为一位GFans。

总的来说,邀请机制虽然风险很大(如果用过的人都不觉得很好而不愿意努力推广),但是一旦成功的话,任何邀请者都变成了你的义务推广者,免费为你推广你的服务。至于如何控制邀请的数量(是好像Orkut那样的无限邀请,还是Gmail这样的有限邀请,或者Wallop那样的需要申请的邀请),这个我还在研究。

2005年12月22日星期四

Office 12, menu byebye?

在Goowy听一个名为TWiT(this WEEK in TECH)的Podcast,听到某位podcaster说他的Palm LifeDrive已经Crash了,另外一位podcaster则说他的是TX,狠狠的打击了我买LD的信心而让我决心买TX + 1G SD,呵呵……

好,说正题,TWiT说道Office 12将没有菜单,取而代之的上下文项目,现给大家一个感性认识,有关的PCMagazine.com的文章在这里:
http://www.pcmag.com/article2/0,1895,1888081,00.asp
或者可以仅看截图你就明白新的上下文项目是怎么回事:(留意原本菜单栏的地方,不再是固定的菜单,每张截图上那个地方出现的项目都不同,是上下文相关的)http://www.pcmag.com/slideshow/0,1206,l=165570&pg=0&s=1739&a=165566,00.asp

大概就是这样的:原本菜单栏的地方不再有固定的菜单栏,而是上下文相关的菜单项目,如果你当前选中的是文本,出现的就是文本格式啊、缩进啊、对齐啊之类的玄想;如果你当前选中的是表格,出现的则是自动套用格式;如果当前在画布上,则可能出现插入文本框、插入直线等。

实际上我觉得这是一个从Computer Operator到Service Comsumer的转变。真正的Service就应该是这样的:持久稳定的,随传随到的,但又绝对不影响消费者的享用,本来需要亲自做的东西你只需要想一下或者说一下那就完成了。正如一个好的Waiter,首先必须随传随到啦,在觉得你需要服务的时候主动出现(例如你不小心把杯子摔到地上了),在你需要主意或者行为的时候出现上下文选项甚至是向导式对话(例如你说“我们再点一个青菜吧”,他会告诉你什么青菜好吃,接着你会问“一个例有多少,够12个人吃吗”,他要比划给你看或者告诉你够不够),最后就是在你不需要他的时候他最好不要出现更不要打扰(不要跑上来问我是否参加“参观体验改进计划”)。这就是Service??我不需要主动理解Service的规则,或者是Workflow这样严格的东西,我只需要按照普通的思维或者以后的其他Service使用习惯来做,然后Service应该为我提供良好的体验,在我不是Service Provider的时候我完全不需要了解Service的细节,必要的时候就在Service开头提供Agreement来确认双方法律责任就是了。

未来的UI,应该逐渐趋向Smart和Rich。Smart不是任何一个Programmer能够做到的,除非出现一个那样的引擎(类似Text to Speech那样的转换引擎),能够让用户输入他的指示,然后自动寻找软件中能够匹配的操作。Rich则主要通过类似Flash这样的东西来解决,特别是对于现在还很Thin的WebClient来说。

2005年12月21日星期三

谁说Google首页页面简介不搞门户的?!

今天打开Google首页,发现原本在www.google.com/ig的"I Google"已经迁移到首页并且整合了原本的搜索输入框。(不一定每一个人都能够看到,可能需要Google Account的登录,甚至以前关注过ig的用户才能直接看到。点击“常规主页”能够回到原版Google。)

以前一直说Google不搞门户,完全靠搜索。对比门户堆满内容的首页,Google的首页只有简介,只有一个输入框和几个按钮。但是现在Google也跑去搞门户了,不过当然是所谓的Web 2.0门户??不通过编辑而通过聚集微内容来组织内容。看来这是未来发展的方向,至少Live.com和ig都代表着这个方向。现在校园内都是老式门户和论坛,少数地方提供Blog,更少数地方提供SNS式的交友与联谊网站,如果现在开始做Feed Portal投放校园肯定有出路!

Feed Portal之后是什么?然后又从Portal回归Search?那个已经出现了??现在已经出现基于Feed的搜索,Feed Portal本身就已经整合了搜索Feed的功能,虽然暂时搜索Feed的结果好像比较让人郁闷,因为几个关键字得到的一个Feed往往是因为里面的一篇或者几篇东西符合搜索条件,这和你愿意长期订阅一个Feed根本没有任何关系,况且现在Feed的独立性也太强,唯一的关联性就是多个Entry在一个Feed内。可能要等TrackBack或者类似技术推广开来,能够建立类似PageRank那样的基于Feed之间关系的Feed价值评估,才能够建立完善的Feed搜索。

之后会是什么?Web最大的问题我觉得就是不能Push只能等用户来Pull,要能够Push又一定要装客户端,这是让人最不爽的地方。Email或者SMS算是一种Push的手段,但是未来是整合到Web,还是Web发展一种专用的Push方式,这个就难说了。别以为Web不能Push,就好像我们以前不懂得将XmlHttpRequest用于AJAX一样,现在我们也能在用户的浏览器上开一个隐藏Window/Frame来Push啊,不过要求用户不关浏览器,将来这方面可能能够获得突破,特别是XAML和XUL等的发展。Live.com加上Longhorn的Sidebar理论上就能够实现Push了,不过以来的就是MS。

2005年11月11日星期五

Google Desktop Search Enterprise 需要 Google Search Appliance?

在Google Desktop Search Enterprise的截图里面,能够看到多了一个"内部网"的搜索标签。下载来看,原来是普通的GDS加上一个组策略文件,在组策略中可以定制该标签指向一个??Google Search Appliance??哦?什么来的呢?Google一下先……

原来就是Google卖的刀片服务器,价格:$30,000起,Faint...

现在我有个小小的Intranet,不过连$2,995的Google Mini都买不起,我只是想提供个小小的Search服务。不过我继续看GDS Enterprise的Document,发现它本是也不是直接支持GSA,它需要用XSLT来把从GSA获取到的搜索结果转换为它能够识别的XML然后再使用。哦……如果是这样就舒服啦,只要有一个Intranet搜索引擎就行了,不用管它是否是GSA,关键就在于它的搜索结果能够输出为GDS支持的某一种XML格式,然后GDS就能够把搜索结果整合进去。 嗯……这样设计确实不错,继续研究下如何实现……

2005年11月9日星期三

百万网站

不知道这算不算病毒广告,不过应该挺有效,起码我都参与传达了(不过地址不使用链接):
http://www.1baiwan.com

这里是简介:
http://www.1baiwan.com/Introduction.html

其实我看到那个用象素画风格做出来的全球最高虚拟大厦的时候,就想着为什么"楼主"不考虑未来的层用来卖呢?或者整个网站卖出去,肯定也能赚不少钱。现在这个"百万网站"终于这样做了,呵呵……大家或许不明白,那还是点击上面的网站去看看如何百万法吧,其实就是首页有一百万个13px*13px的个子,每个的售价为¥100(出售的为永久使用权),网站承诺至少维持5年。

2005年11月5日星期六

大家应该去看看现在通过网站提供服务这一领域的变化

最近Google vs Microsoft的事情越来越多人关注,Google不依赖于脱离网络的软件让MS在软件方面的优势完全表现不出来,而且Google也找到了它的广告形式,这足够让MS不爽的了。

不过MS现在已经逐步改变战略,开始学Google了——不需要太多创新,以足够的资金作为优势,模仿和跟进也就足够了。(顺便所以下,Tencent在国内也是这个策略,不过它模仿的是国内其他厂商如何流氓的做法,例如据说最新的QQ2005正式版就内嵌了Tencent的搜索/实名插件,这个东西会自动把系统中已经安装的其它同类插件Disable掉,并且也胆敢在Agreement上直接说因为QQ和这些插件存在冲突可能导致这些插件不能正常运行。)

MS最近就推出了称之为Windows Live的Beta服务,大家可以去Live.com看看,其中包括可以申请的Windows Live Mail Beta(Hotmail升级项)和即将开放的Windows Live Messenger Beta。最近几天的Google News科技版中都有有关的新闻,昨天说Live.com收购了提供网络硬盘服务的FolderShare.com,今天说MS当年不重视"软件既是服务"放弃收购SalesForce.com(一个在线CRM服务网站)现在才来重视此事已经太晚了。

暂时来说,我们都能看出Live.com其实是希望通过一个整合的平台应付Google众多分散式的服务。Google的服务以前总是先来Beta,可能还基于Invitation机制,过一段时间了才进行Localize,虽然后来Google Account出现后所有服务都依次为登录标准,但是通用登录和Portal之间还是有差别的,IGoogle虽然在推进此事(最近有了中文版),不过说到做Portal方面应该还是MS有经验,就算是个性化Portal方面MS起码也有my.msn.com这个基础,所以Live.com依靠MS的资金是有可能赶上IGoogle的。

然而MS真正的竞争对手不是Google一个,我们现在这些在做小软件或者还在做网站不过是给别人拿去部署的也面对这些竞争。那就是一些直接提供服务而不是提供下载的网站。由最不像提供软件的del.icio.usflickr,到Coo介绍我看的那个类似wiki的可以用于Collaberate的网站,再到最近发现的writely.comnumsum.com。第一个虽然是服务,不过是完全面向大众的;第二个开始转向面向个人和组织,因为你不能够下载它并在自己的站点上部署一个,所以必须用它的;第三个则已经由"此站点不能下载并部署"变成了"此软件不能下载并使用",writely.com和numsum.com分别针对文字处理工具和表格处理工具,然而完全基于Web确保证了不可能盗版。
虽然这些网站暂时还没什么盈利之道,最多放一下Google AdSense,因为暂时他们都是处于探索性的,特别是针对零售版软件领域暂时还无法追上零售软件的功能。不过一旦这种做法找到了盈利之道,可能就真的能够大大减少零售软件。但是可能到时候可能私服也将出现,正如中国从前有人不知道正版只买盗版现在有人不知道官服只玩私服一样,零售市场收缩是否就确保了利润的收入,这个暂时还很难说。

另外,MS可能又在背后偷偷乐了,为什么?大家慢慢忙DHTML和所谓的AJAX吧,它的Avalon随后就到。Google花钱把DHTML的发明者从MS挖过去了又怎样?总的来说你还是得按照MS当初制定下来的标准做Web和玩这场游戏。即使你的Web再好,Avalon一发布可能就都成为历史??可能别人仅仅需要打开一个XAML写的页面,后台下载一个.NET DLL,那就是一个程序,点以下Install那个.NET DLL就会从Cache迁移到永久保存的目录,那个XAML页面的地址就被添加到"程序"里面,普通Web还有什么意义?可能有人说,Avalon仅仅适用于Longhorn,即使推出兼容低版本的Windows兼容软件,或者类似mono那样提供Linux上的对应开源项目,适用范围还是在PC上,而支持Web的设备则周街都是。唉……以后可能支持Web和Web Service的设备确实周街都是,你随手捡个MP3都说支持,但是它们可能支持AJAX吗?或者是基本的DHTML?现在PPC和Palm都还不能完全支持呢。所以未来不一定属于HTML,而可能属于XAML或其它后来的类似开源项目,这个是很难说的。如今PC的架构是已经确定了,它不是NC就不是NC,除非有一天主板加上了XML处理芯片或者CPU/GPU提供了对XML呈现的直接支持(这里的XML指未来的某种支持动态的基于XML的语言),否则通过一种标准的网络形式售卖服务即售卖软件的日子还很远呢。

TextGem v2 - 基于类似Sharepoint技术的CMS

TextGem在开发的时候,本来仅仅考虑用来做wiki。wiki做完了,我就开始考虑把它用于blog和forum??因为大家的ContentData格式都是一致的,不过UI不同,于是TextGem Pro出现。TextGemPro中应用了很多新奇好玩的构思,例如实现了HTML编辑器,添加了支持RollBack的Config,支持Key的映射……虽然都是没什么用的东西,而且把TextGemPro变成四不像,不过挺好玩。可惜它现在实在是太过四不像啦,所以我就算要把它重新做成单一目标的产品,也不知道"单一目标"定为什么好。

然后,最近遇到了一些问题,就是我见到好像TLF或者一些其他论坛,通过规定一些发帖规范把某些板块的帖子格式限制到符合一个标准,然后就可以自己写一些小软件来分析数据库,按照帖子格式来进行数据分析,作统计工作量等的一些工作。我在想,其实很多论坛,它有特色就在仅仅在于它的数据表多了一两个字段和多了一些相关的数据逻辑,仅此而已,我希望提供一种论坛能够轻松的自定义增加的数据字段和自定义逻辑。

开头的时候,我在做有关ASP.NET的事情,所以我的设计思路是很OO的,也是完全面对开发者的。那时候考虑的是,例如好像CSDN那样的记分系统,完全就是可以当作一个插件来看。首先要严格定义一个IBoardExtension的接口,类似ASP.NET有一个OnInit->OnLoad->OnPrerender->OnRender这样的一个过程,IBoardExtension应该支持一系列的事件,例如OnPreinstall和OnInstaller将在论坛发现新的IBoardExtension时调用而让这个插件有机会去检查是否已存在低版本需要删除、是否需要建立/升级此插件需要的数据表;然后OnThreadListPageRender、OnThreadPageRender等事件则在呈现对应页面时发生,插件此时就有机会去读取Threads、Posts等有关对象然后在Page上做有关的改动;OnNewThreadPageRender将在呈现"发新贴"页面调用,如果插件需要用户填写"点数"这项属性可以在此时操作Page,而OnNewThreadPagePostBack则是用户提交了"发新贴"页面,此时Extension要检查数据是否合法,以及是否对数据库做什么读写操作等。

现在发觉,当时的想法把页面限死了,因为所有IBoardExtension有关的事件,都是和某一个页面某一个事件绑死在一起的,如果仅仅是考虑论坛和插件的功能,那已经相当足够,因为一个论坛的页面大概也就那么多,无非是主题列表、主题里面的贴子/回复列表、发新主题、发新贴等等,UI的大体是固定的,仅仅是Extension在这上面能够对Render和PostBack做一定的操作。但是如果要支持wiki和blog这些和forum拥有类似数据表结构的东西就不行了,这需要一个更加flexible的设计。

这个更加flexible的设计,就是学习Sharepoint引入WebPart的概念??一个WebPart自身就包括显示部分与逻辑部分。实际上,我非常认同一个拥有良好flexibility的东西,必须遵守MVC分离的设计,至于它是否使用某个设计模式那倒不重要。应用MVC分离,这意味着每一个WebPart本身都要拥有MVC三者,而且这三者之间要松耦合然后他们都去和系统自身的MVC耦合。也就是说,IBoardExtension那样完全不区分MVC的提供一队事件是不行的,必须提供一种更加好的方式,让Extension继承/支持某个东西,然后就可以分别对MVC三个部分扩展编程。

详细的TextGem v2设计还在思考中,不过这并没有脱离原来的TextGem.NET开发三部曲路线??首先制作核心,然后制作应用,最后提供用于制作应用的开发工具。TextGemv2首先要做的核心,它不会像制作一般论坛那样,受到表情符号、用户头像等一系列琐碎麻烦问题的困扰,因为这一切都属于应用而不属于核心,但核心的设计就是要兼容这一切将来可能要添加的应用,所以需要花比较长的时间去做设计。

2005年10月30日星期日

基于发送者的贝叶斯~

现在在这个荒岛上,好像大家很习惯一种发布Announcement和Ads的方法,就是群传群??通常一个人参加了近十个Q群甚至近二十个Q群,如果他在一个群看到一个Announcement或者Ads,并且他觉得这个Announcement应该转告给其他人或者他觉得这个Ads的发起人值得他帮忙,那么他就会把信息贴到其他所有群。这种方法不能说"有效",因为你永远不知道信息传到多远了,有多少人接受了,但是他在信息流的控制方面看起来也有一定的根据??你觉得值得你转发的东西你就转发吧,而这又影响着你的信誉度,因为如果你转发垃圾太多别人就干脆把这个群屏蔽掉了。

现在我想干脆就做一个基于这个原理和SNS的通讯系统,只支持近邻的发送而不支持DirectMail。其实我很早就觉得Orkut应该禁止DirectMessage,因为我收到的Spam实在太多了,过了一段时间才得到改善。后来看到Linkist有这项功能(你可以设置不接收DirectMessage仅接受来自好友后通过好友传递的Message),觉得这样东西确实值得做。

好了,到说主题了,我想做的这个东西就是基于发送者和传递者的贝叶斯信息过滤系统,允许发送的信息有两种??点对点和广播,这样设计有点类似TCP和UDP。无论是哪一种,信息都只能通过好友传好友,虽然这个过程是全自动的,但是你也可以要求启动过滤。全自动的意思是,如果你的两个好友是陌生人,他们通过你传递信息,你就好像网关一样,你可以选择不阅读这些信息就让他们自动转发;而允许过滤的意思是,作为网关,你其实也有权查看流经你的信息,即使加密了你还是可以大概看出信息类型(或者你干脆不允许加密信息经过),你有权自动(基于规则或基于贝叶斯)或手动的过滤掉一些信息。

情景1:A知道陈扬星期天来东校区做讲座,于是希望身边的好友都知道,于是他用广播模式发送了这条信息。B是A的直接好友,接受到了这条信息,觉得确实应该让大家都知道这条消息,于是点击了消息阅读框下面的"自动转发"按钮,于是B的好友也看到了这条消息,同时基于贝叶斯的统计,B对A发送的信息的信任度增加了。然而很不幸,B的好友C对这些活动毫无兴趣,觉得B整天发这些东西给他很烦,于是他点击了消息对话框下面的"垃圾"按钮,这个按钮拥有"关闭"按钮更多的更能??C对B的信任度下降了,同时C把这条消息的MessageID自动转发给他的好友并告知为Spam,这个Spam提示对于越是信任C的好友效果越明显甚至还会自动转发给下一级好友。

过了一段时间,这个消息又传回到B那里了,不过由于MessageID相同,B的客户端没有提示有新消息更加不会自动转发此条消息,而仅仅是在这则消息上面增加了Hit的数值。

情景2:K下载了这个软件,想用来群发广告——通过P2P的方式发送广告确实是个不错的主意。K加了一些好友,然后开始发送广告,开头他的这些好友还是愿意帮他转发的,不过很快发现他们的好友开始不怎么理睬他们(因为Spam多信任度降低更多的信息被过滤),他们也不再愿意帮K转发广告了,主动把K发过来的广告当作Spam来统计,结果K变成了信息孤岛,他说的话不再有人信了。(这里是基于大家都只加现实中认识的人这一原则。如果是网友的话,先通过中间人的自动转发功能联系一段时间,然后再加为好友。)

主动发送或者转发广告的人都是不受欢迎的,而且这个不需要大家开口来声讨,我们的系统知道如何去处理。

情景3:Z最近认识了好友Y的好友X。可惜Y经常不上线,他们要经过Y进行消息转发的这条Route的Ping值太高了。幸好Z和X之间还有另外一条Route,虽然中间隔着的人比较多,但是Ping值低,他们两个觉得发送的信息又不是什么大秘密,于是选择了走这条虽然可能有几个比较陌生的人,但是Ping值低的Route,很快他们就都主动把对方加为自己的好友了,于是就能够直接通信了。

2005年10月28日星期五

在做“作业提交系统”的那位来看看,你会faint死的~

Windows SharePoint Services 中文网站模板:
http://office.microsoft.com/zh-cn/assistance/HA011929182052.aspx

这个是微软的增值计划的一部分,你去看看下面那个"学校班级网站模板",什么课件上传下载、作业提交,都有了,很faint吧。所以说,如果你有一台足够好的域­服务器,给你一个Sharepoint,就算不作为WebFarm,自己做一下二次开发弄一些WebPart就很好用,剩下的就是要有一个好的ADSI程序用于­账号管理。现在MS连给中国学校用的WebPart都做埋了,那么我们能够做的东西就更少了。

《Joel说软件》中说到,如果我是偏执狂,那么我会说MS肯定不会为它当前领域及纵向相关的潜在领域提供开发工具。这句话看起来也不假,呵呵……

2005年10月22日星期六

发现了一个很好的Wiki:MoinMoin!

http://moinmoin.wikiwikiweb.de

看起来很不错的东西,自动根据客户端语言来显示,用Python写的。不知道在Windows Server 2003上面要支持Python是否麻烦,如果不麻烦,我也想装个来玩一下。

现在我喜欢做的是,像verycd那样用已有的引擎作为后台,然后自己写一个前台的只读门户,那样会很轻松。因为门户不会进行写操作,所以不用担心改乱了数据,­只要后台那个引擎是足够稳定的,那就可以放心了。

2005年10月1日星期六

Google、SNS、Web2.0……这一切意味着专家继续创,但新平庸的人就不要创新了

我的论点只有一个:我们期望有效的控制信息爆炸,特别是通过网络来克服这个网络自身带来的问题时,最"有效"的办法自然是减少信息的创造。

Web farm? Who's farming? Human. Who's harvesting? Machine. Quite like the Matrix, doesn't it?

这真的是一个很奇怪的问题,我们每天在写Blog,上豆瓣列举自己所读所看所听并且还附上评论,还有在Groups上交流,我们到底贡献了多少,其中造成了多少­的成本和收益?或者说不应该用成本/收益计算方法,而有新的计量单位和计算方法?或许现在等着某一个在信息学领域提出一个伟大的计算公式,能够和马克思提出商品­交换的实质以及引申到资本主义剥削实质一样震撼。

反正在当前,没有任何公式可以利用,我们只是凭兴趣去贡献自己的信息,有时候至少保证贡献了感觉没有吃亏,例如上论坛赚精华贴然后升等级换取更多的好处。有些时­候,我们根本没办法判断贡献信息到底对自己是利是弊,对别人也会不会是弊大于利。这听起来很好笑,但是难道有人能够证明你贡献信息就不会对别人造成坏处吗?

Friendster起源于6度空间理论,也就是说世界上任何两个人之间只隔着6个人(以前Coo告诉我的是20个人),也就是任何人都必然在你的朋友的朋友的­朋友的朋友的朋友的朋友(6次"朋友")的圈子之内,不过英文中采用Degree这个词表达经过了多少次"朋友"运算所以叫做6"度"空间。如果Friendster仅仅用在结交朋友的朋友,因为朋友的朋友更加容易成为朋友,那还算是一件好事,不过其应用也仅仅在于交友。如果Friendster,加上Google搜­索模式,那么理想的事情就是当我想办一件事的时候,我会考虑我需要什么人际关系,然后可以搜索,然后Google根据HumanRank排序提供结果给我看,我­通过它给出的"连接"联系上了排在搜索结果前几位的人,然后托其中一位帮我把事情完成了。

然后让我们回到贡献信息的例子,类似6度空间的理论,只要信息足够的多,计算机可以通过组合信息得出任何人类已知甚至人类未知的事情。这个如果在那个Googl­e在2014年垄断传媒界的例子里,会是很好的事情,因为每个人贡献的信息可以选择Private还是Public,而Google的EPIC能够根据Publ­ic信息自动组合出或者说是写作新闻。然而实际上,正如在6度空间理论中你永远不可能知道你是否出于某条关键链上,你现在所贡献出来的一点点信息也可能存在于某­条非常重要的推导链上,然后一旦这个推导完成,到底你做了什么你也不知道。正如《Google成功的7堂课》里面提到的一个案例,某人失踪了10年(至少他的家人如此认为),一直都找不到他的下落,最后是在Google间接搜索到他出现在10年前某一个州的车祸伤亡名单上,这才确认他已经死了。我们根本不知道随随便便­说的一两句话,可能导致什么,呵呵……

2005年9月10日星期六

可编程样式表

Coo曾经跟我说过,如果CSS里面能够自定义颜色常量(例如Red=#FF0000就是一个颜色常量),那就好了(那意味着你可以定义一个ContentBo­rderColor和一个HeadBorderColor,可能当初它们的值一样,当你需要修改其中一个的时候你就不需要小心的查找和替换以免替换多了或者替换­少了)。Coo的这个想法暂时只有通过xslt实现,MSN Messenger的聊天记录就是通过xml+xslt成仙的,而其中就有很多样式是通过自定义常数一次声明的(通过声明自定义参­数)。

我最近在弄一个东西,也发现如果样式表支持可编程那会好很多。例如我在一个地方使用了font-family列表,但是如果浏览器在采用font-family­上的后备字体显示时,我就希望padding等属性有一定的修正,但这个暂时做不到。再举一个例子,例如我设计一个ASP.NET控件,而它内部包含一个子元素­,我希望这个子元素的padding是整个控件的padding加上1px(也就是"继承"且"运算"),但这也是无法通过样式表编程做到的,暂时只能够在AS­P.NET里面主动去运算出这个元素的padding然后显示输出这个padding,而我想做到的效果是例如:
<div id="parent" class="parentLayer">
<div id="child" style="padding: +1px">
</div>
</div>
这时候,无论parentLayer这个样式怎么样,child的padding总是比它多一个pixel。

不知道W3C什么时候才开始重视样式有关的东西,可以让样式更加结构化和可编程。继续这样下去,Web将完全被Web Service取代,变成所有Web都是给机器读取和分析,然后再提供给人看。

2005年9月4日星期日

多层网络SNS及泛信息发布系统

自从高二暑假完成TextGem之后,我就没做过完整的项目(高三升级TextGem到TextGem Pro),CommentMe、Xilite等项目都在概念设计后放弃,这两个项目都是ajax气息太浓,我暂时无法掌握一种良好的ajax开发和调试方法,完成概念设计后一旦进入需要服务器端和客户端代码同步设计的阶段就让我无法进行下去。至于Quickling,也是出过一版Quickling Lite for Acess,不过因为硬盘问题现在代码都不知道哪里还能找回来了,而且此原型的安全性还是存在一些我能够发现的漏洞(当然,作为守方认为的高级漏洞,对于攻方来说就是超高级漏洞了,很难找到的)。

现在我准备重新回归完善的先Design后Coding过程,做一个SNS核心的Web平台。

首先解释一下多层网络SNS的概念,之前friendster和orkut只能用于链接朋友网,用户信息真实性稍低,甚至有些朋友仅仅是网友;而linkist等商务SNS则采用真实姓名和真实信息(只要别人都用真实信息,一般新人都会愿意填写真实信息),主要用于商业上的联系,就是把“朋友的朋友更容易成为朋友”的理论拓展为“合作方的合作方更容易签到合同”。我现在所谓的多层网络SNS就是允许用户以不同程度的真实信息生存在不同的关系层中,例如用户进入后就会发现页面有3个Tab:工作、生活、家庭。工作方面是像linkist那样的实名商务连接方式,学习orkut那样能够单方面匿名对对方做出评价,例如能够设置年交易额1万、10万、100万,或者可以设置可信任度;生活方面是像orkut那样的匿名朋友圈,你能够通过Email、真实姓名等方式查找现实生活中你认识的朋友是否也在SNS上面;家庭则是实名的家庭关系网,可以选择关系类型,然后自动生成族谱(玩过Sims2的都知道这有多方便)。关系在不同层之间切换会受到一定的阻碍,也就是说切换层相当于一个距离加权比较大的关系,在搜索最短关系链接的时候优先考虑尽量少层切换的。

另一种关于多层SNS的想法就是,我不直接细分层,而是提供“连接方式”,然后任何一个人都可以匿名的指定他和另外一个人存在的若干链接方式,而更多的选项则是基于“链接方式”的选择的。例如你选择“同事”,那就填写有关上下级组织结构图的属性;选择“亲戚”,就填写亲戚关系;选择“朋友”,就填写熟悉程度等。

另外就是泛消息发布系统,在linkist我看到一种设置,就是不允许非好友直接发信息给自己,所有信息必须经过人际链转发。虽然我没用过,但应该就是发送的信息必须先经过好友审阅,如果好后不通过就不能够传递,当然这也就是发送的不再是私人信息,因为有第三方人员能看到。另外发布和传递spam一经Report将会受到惩罚,这也是个很好的做法,因为orkut上面的spam就不少。而我现在则选择一种直邮和传递邮之间的方法,就是在发送信息的时候信息会自由在朋友圈内扩散,用户收到信息后将可以选择觉得有意义或者没有意义,如果选择有意义则促进该信息在此接受用户的朋友圈中扩善,否则将是抑制。这样就能够将SNS里面的“关系”发挥到信息传递上面来,既能够抑制spam,又能够自动组织和提供用户感兴趣的信息。

2005年9月2日星期五

Google Local中文版可用啦!

中文版叫做"Google本地搜索",地址为bendi.google.com。大家不要去local.google.com,因为那里仅仅是汉化的界面,地区无论你输入什么都返回"不可识别"。

我刚刚试用了一下,搜索"中山大学"@"广州",发现结果还很好,而且有maps.google.com的那种详细的街道图,可能maps.google.com也将会有中国的街道图了。另外地图上写着地图服务供应商是mapabc,我搜索到的信息是"Mapabc.com成立于2003年4月,是从事地理信息系统(GIS)研究与应用推广的高新技术企业",现在做地图的服务上越来越多,而且也有开放API的,看来以后地图也越来越廉价了。

2005年9月1日星期四

游戏年龄与实际年龄

根据我多年的观察,一个人的游戏年龄基本上是与实际年龄无关的,并不会因为实际年龄大而游戏年龄增长得快。无论是像我这样从小学开始玩PC Game还是好像我的一些同学那样高中甚至大学才有比较多时间接触PC Game,实际上开头的玩法都总是单调和追求表层刺激的,而需要等游戏年龄增长才能够理解游戏的更深层次玩法和艺术价值的一面。

举一个最简单的例子,例如赛车游戏:(这个实例不包括在现实生活中熟悉车辆的人士)

对于一个游戏年龄低的人来说,他追求的就是最表层的刺激,例如视觉效果和速度感,无论是当年NFS2作为第一个3D赛车游戏推出还是后来的NFSUG模仿《速度与激情2》的光影之夜,这都能非常好的满足初级玩家的需求。初级玩家不会懂侧滑(现在《头文字D》宣传Drift过后是另外一回事),甚至不擅长使用刹车,他们喜欢一直按着加速键的那种感觉,弯转不过就撞上,然后速度降为零,低速出弯后又再下一次的加速。这听起来就好像我妈说我小时候还不会走的时候,就喜欢高速的向前爬,直到撞上墙,然后我会咔咔笑,然后又转过来加速撞另一堵墙。

然后,虽则游戏经验的增加,或者看一些游戏技巧的文章或者贴子,玩家的游戏年龄会增加,它开始知道赛车是存在所谓的“最优路线”,入弯的时候应该减速和内切,出弯的时候应该加速和外切。但是,这时候他只是觉得,只有在必要的路段跟随一定的规律减速和入弯,在其他地方仍然可以追求速度最大化,无论是追求刺激还是他直觉认为一段路程内速度最大化肯定让他在整场比赛中获得优势。这时候他往往会选择在入弯前还是不停的加速,到需要入玩的时候就死按减速,任何时候加速和减速必然有一个键按着,因为在不需要减速的时候没有任何理由不加速。

之后,可能他开始对赛车游戏有Feel了,他可能能够明白到油门和刹车大多数时候都不是踩死的,正如现实中的车辆使用一样。最优路线上并非速度非加即减,而是很多地方都是保持速度或者稍微加减。同时,他还可能开始掌握侧滑等技巧,甚至尝试在游戏中玩花式。

为什么我要讲游戏年龄?因为这意味着中国玩家的趋向是会发展的。张朝阳最近嘲笑陈天桥,说他是赚快钱的,而事实上很可能就是这样。现在主流玩家确实水平很低,但这不意味着是“劣根性”所造成的长期影响,而更可能是现在很多人的游戏年龄很低,他们只能追求最表面的刺激感,然而如果想面向这个去做长期投资,那就不适合了,因为玩家的游戏年龄一旦增长,他们就会开始挑有深度的游戏,而中国和韩国的游戏制作者能否满足这种需求暂时还很难说,很肯能东方网游只是一个能够撑的更大的泡沫。

Sense for AdSense

我在论坛发了一帖关于AdSense的帖,开头广告都是Google AdSense的广告,后来竟然出来一条链接到以下站点的广告:
http://keywordcountry.com/

这个站点是做什么的呢?就是收集和更新AdWords的价值,例如它知道的大于$50的AdWords有150个,假如你的网页什么时候放上一个而AdSense又正好提供了那么广告了,只需要有用户轻轻一点你就有$50了,两次点击你就能够收到$100的支票了。

Sense for AdSense,就好像我之前说过做到AdSense级别的Wiki-Spam那么Google就很难判别了。Google总是以为能够通过优化算法把自己调整到一个完全旁观者的角色来服务,然而实际上“黄雀在后”的情况一直都会出现,除非Google改用量子计算,遵守“测不准原理”,那别人就真的很难应对。

Google啊,现在已经开始有人觉得它变得高傲和自大了,本来的Silicon Valley新兴和希望现在却变成了威胁,因为它把其他小企业的人才都抢走了。有人说,MS终于开始向IBM的温纯型转变了,而Google则在向MS的霸道型转变,这是否暗示着这时企业壮大和不断增加垄断领域的必经之路?

2005年8月24日星期三

Google Talk

http://www.google.com/talk

Google又找到了一样成本很低的投资,那就是基于Jabber的Google Talk。我觉得这样的投资方法很聪明,它不需要研发什么新技术,不用好像MS为了摆脱竞争对手那样建立标准外的标准,需要的仅仅是用自己的名字去包装一项老技术,同时整合一些自己擅长的其他东西(暂时它只整合了Gmail Notifier,连任何一项搜索功能都没有整合进去)。

虽然Add Friends的时候默认提示someone@gmail.com,不过可能所有的Google Account都可添加。另外它还可以语音,当然也是基于Jabber的。

如果你用Google Talk发Invitation给别人,那么自动同时也发送了G?mail Invitation,当然对方可以选择要Gmail或者说我已经有一个Gmail Account。

另外我发现Google Talk在Gmail用户范围内传播得很快,可能因为Gmail?用户早就习惯了这种“人传人”的方式。无论是碰巧还是策划,Google在这件事情上是很成功的,习惯MSN式大幅宣传才取用的人就是只能接受大牌子大宣传的产品;而Google从来节省宣传?费用,靠人传人的口碑,而他所有产品都靠这样推广,它的用户群也?非常习惯这种方式,Google在自己的用户群中推广新服务非常容易。

这说明了,当你按照一定的方式招揽了一定的用户,以后最好都用同样的方式推广新的服务和产品。

另外Google Talk和新的Google Desktop Search 2 Beta(仅英文页面可见)的SideBar也能够组合起来。Google Desktop Search 2的SideBar可以说是把Windows Vista的SideBar的功能都做上了,而且都是Google服务,这招够狠!这个SideBar能够整合Gmail、Talk等功能,内嵌快速搜索(而且还能够搜索“开始菜单”里面的项目,这和Vista隐藏掉开始菜单里的“搜索程序”然后提供快速搜索是一样的)。Google这种利用轻量级软件以快打慢真的很绝,Vista既要给用户预览它的新功能,但是它的开发缓慢又必然给Google用轻量级等效软件去抢占市场份额,当年MS想用MSN Game整合到Windows来抢占联众等桌面网络游戏市场都不怎么成功,反而Google这种敏捷的方法可能能够从MS手上抢占到份额。

2005年8月19日星期五

继续说说窄告和户外广告

我总结出来的规律是,"用户在浏览正文时越是不太确定他想要什么或者他想要的是否在此时,那么窄告的成功机率就越大"(这和我上次的说法不矛盾,目标明确的用户停留时间通常也长一些,在用户目标不明确的时候用户必然是不想停留太久的)。简而言之,窄告投放在用户"直奔目标"式的阅读区域是没有任何效用的,因为用户根本不会看;而窄告投放在搜索结果是最有效的,因为搜索本来就表明用户目的不明确。暂时来说,我对窄告持保留态度,对于针对性投放这个我支持,这是提升成功率的一种办法,但是对于AdSense这种周围都可以放置的方法我反对,这样做太过"散弹枪"式了。

说会上次提到的地铁广告,地铁自己说是"不受风雨影响的户外广告",我就挺喜欢这样。我说过,户外广告往往属于你不得不看的,因为你不需经过或停留在某一个地方,你的眼睛也需要地方停留(除了你的脚尖)。

现在很多论坛在登录和发帖后都会出现一个"3秒后自动转跳"的页面,我怀疑是因为如果使用Access等低级数据库Insert数据后马上Select是读去不出所以要给时间达到延时吧(这个延时实际上不需要3秒,即使用户马上点击转跳也可以),大多数论坛这个转跳页都是很空白的,不过CSDN登录后2秒转跳那个就不是,那个是有广告,虽然广告不是刻意的而是因为模板而带有的。这让我想起来网络也可以发布"户外广告",这些户外广告就是AdSense最好的补充,特别是那些"当用户直奔目标时"的场合。

在网络上的户外广告其实一早就有,例如GameSpot和IGN的,它们就完全符合我上面所说的,当你直奔目标时中间也得停留一下看看广告,而且不是在浏览正文时用眼角看一下,而是在没有正文时停下来好好看看广告。这些游戏网站的做法就是,在你每看若干个页面(或许只有特定的页面才计数)后你点击下一个页面就会进入广告页,整个页面就是中间一个大大的广告(通常是Flash),下面还附带一个"Next"按钮让你继续去看你刚才点击的目标链接。这样做是非常有效的,因为在这些游戏网站上,玩家通常是逐张浏览未发布的游戏新的公开截图(看原图,每张一页),或者看长长的Preview、Review、Interview(网站把这些文章剪开为n页),无论看什么你总要点若干下"Next",而且中就有几次是碰到广告的,不过这也很正常嘛,你不是付费会员自然看广告。

如果把窄告的定点投放和户外广告结合起来,那就会非常好了。例如在看一篇文章的很多段中,插入一个很有针对性的广告页,那比单纯的AdSense会有效得多(因为AdSense很明显,你可以直接跳过不看)。如果有一天Google也发现了这个东西的好处,并提供有关的支持技术(就是检索多个相关页的内容并且把广告提供在桥页),那它就更加发达了。不过Google现在也很好,起码它这种"我自己好也分享出来让大家好"的做法也让不少小型企业通过AdSense获得了不少订单,足够受欢迎了。

2005年8月13日星期六

Google News竟然能够迁就我的Palm用gb2312输出

在PC上看,Google News是utf-8的,这是Palm所不支持的(好像PPC对unicode支持也不怎么行),但是我还是尝试了用Palm去打开,竟然能够看到,那就是gb2312啦,哈哈!Google News真够人性化哦。

2005年8月7日星期日

使用Google快照的方法

如果你想看某个页面的Google缓存,仅仅需要在你的Google搜索栏里输入cache:{URL},虽然我不知道这样看到的结果会不会和直接点击搜索结果旁边的"Google快照"有什么不同,但是在Google快照长期用不了的情况下,用cache:倒没什么问题。至于为什么这样,我也不知道,或许仅仅是地址上有些差别所以没有封到吧。

2005年8月4日星期四

我不懂 ASP.NET

这真是个严重的问题,而且我越来越发觉其严重性。要懂得ASP.NET语法非常容易,要学习MS提供给你那种RAD开发方法也很容易,但是你无法做大东西,或者说你只能够按照ASP的老路去做大东西,并不能“享受”ASP.NET带来的“优越性”。

要做到“优秀”的Web应用,最重要的就是“分离”(“正交设计”就是老生常谈的问题了)。首先就是Web Standards里面鼓催的内容(Content)与布局(Layout)分离,暂且不说“终极目标”是HTML只容纳内容CSS只容纳布局对于现在的浏览器来说有多么过分(特别是你要兼容多个浏览器的话),我们就现把这几下来作为“第一分离”。然后,就是ASP.NET里面3层式设计,对于ASP.NET来说就应该划分为“编译部分”和“不编译/动态编译部分”,这个算是“第二分层”。这样2*2就已经组合出4个部分,在编写代码的时候某一段代码应该属于哪个部分,一个部分如何引用另一个部分,这就是个非常头痛的问题。

要说明这个事情,我们需要从以前的做法说起。

在“古老”的时代,我们存在一些“古老的假设”。首先,当时没有很明确的布局、内容、行为分离理论,其次当时假设所有这些都属于不编译部分,编译部分都是相对固定的逻辑层和数据层代码(相对小型的系统当然就什么都不编译,因为ASP引用COM组件还是要一定的权限的)。那个时候HTML是个大杂烩,我们控制了HTML就控制了天下,而不编译部分就是控制天下的最重要部分,你写的ASP代码已经完全决定了用户看到的布局、内容、行为。不过即使在不编译代码中,我们也分离出了相对固定代码,这就是我们的include技术欣欣向荣的原因了。一个良好设计的ASP系统里面有良好的include体系,固定的代码都是通过include重复使用。如果你对于为什么要include有疑问的话,那就真应该看看《程序员修炼之道》里面的DRY(Don't Repeat Yourself)规则,任何事情在程序代码中都应该仅仅被描述一次,一旦被两次描述那么你就必须保持两边的同步更新了,一旦出现同步失败你的代码就可能出现不可预料的问题。

然后ASP.NET出现了,它带来了“立体化”的Web模型,最重要的是它提出了Code-Behind和WebControl这两种编译代码的存在方式。Code-Behind代码和WebControl代码都是必须先显式编译后使用的(其实不编译的Code-Behind是可以的,就是<%@Page Src=""%>方式,但是这不是我现在要讨论的东西)。Code-Behind的页面或者UserControl实际上是被编译了两次的,第一次是编译后台代码,生成的类就是<%@Page Inherit=""%>中Inherit指向的Page/UserControl派生类,第二次是在页面被访问的时候即时编译出来的Page/UserControl派生类的派生类,这其中第一次编译就属于上面所说的“编译部分”。至于WebControl则是必须先编译再用<%@Register%>指令引用的,整个都属于“编译部分”。为什么MS要在.NET Framework里面设置编译部分?我想它是相信有一些UI部分的逻辑能够在很高的层次存在一定的共性,这些共性就应该被编译。例如WebControl中最突出的DataGrid,就是一种数据载体需要列表、需要分页甚至对于有些数据字段需要特殊显示(例如一个“真/假”字段需要显示为一个CheckBox是否被选中)的共性。我们也可以归纳自己网站中的一些显示共性的逻辑,自己制作WebControl(甚至TemplateControl或者Control,HtmlControl当然也行不过意义不大),或者继承现有的各种Control(继承HtmlControl是有意义的)。至于Page的后台代码编译有什么意思,这个我就不清楚了。诚然,你可以把Page看作一种Control,但是这种编译是不可复用的,编译来干什么呢?我唯一的解释就是这仅仅属于一种RAD(Rapid
Application Development:快速应用程序开发)开发方式,程序员可以随便拖放控件让后写后台代码并且编译,美工之后再来处理aspx页面,只要美工不毁坏控件tag那么他可以任意添加新tag或者移动现有tag。

然而这种编译方式并没有解决我们原来用include带来的各种问题(至少要考虑什么颗粒度的代码应该include,什么颗粒度的就让它在各处重复),我们变成了考虑什么层次的UI逻辑应该“统一起来”把它们变成编译好的WebControl。关于这个事情我暂时还在摸索之中,我喜欢的做法是把每个页面的核心固定内容封装成为WebControl(其实我早在TextGem的时候,就已经是每个页面的主要内容封装到一个function里面),例如一个登录表单的两个TextBox和一个Button就封装起来。同时一些公共元素例如Header这种以前习惯include的东西有时候也封装为WebControl(不过我现在更加喜欢封装为ascx,因为这部分应该属于容易编辑的UI代码,不应该被编译死)。封装为WebControl的东西大多数是样式无关(仅使用全局样式)的,样式有关的或者我考虑到以后要修改HTML的东西我都仅仅封装为ascx,或者封装为TemplateControl以后必要时能够通过改Template部分修改输出的HTML。这就是我们现在能够做到的事情。

至于未来,ASP.NET 2.0会为我们提供WebPart和MasterPage等优秀功能。WebPart能够让我们轻松实现Sharepoint才拥有的门户页面效果,每一个信息栏都是一个WebPart,能够被所以拖动和缩放。至于MasterPage则能够制作一个固定的模板页,制定其中几个地方为ContentContainer,然后在aspx里面引用这个MasterPage并且用同ID的Content控件对应填充ContentContainer(Content控件里面可以放置任何东西),这对于使用少数模板覆盖全站的设计非常有用。不过其实我非常需要一样东西,暂时看起来没有的。我希望有一种松散型复合控件,例如我订一个登录表单控件,派生自HtmlForm,然后必须包含用户名和密码两个输入框(HtmlInputText的派生类,或者是实例)以及一个提交按钮,然后我可以按任意方式布局它们,例如:

<LoginForm:Form runat="server">
  <span class="inputSubject">UserName:</span>
  <LoginForm:UserName class="inputText" runat="server" />
  <br />
  <span class="inputSubject">Password:</span>
  <LoginForm:Password class="inputText" runat="server" />
  <br />
  <LoginForm:Submit class="inputButton" runat="server" />
</LoginForm:Form>

这会是一种很好的控件结构,因为我定义了一个<LoginForm:Form>必须包含<LoginForm:UserName>、<LoginForm:Password>、<LoginForm:Submit>各一个,然后选择上述布局或者Table布局或者其他布局方式就在aspx中定义,那就有效实现了布局代码不编译逻辑代码编译的分离。布局代码方面,既然是融入在aspx文件中,那么我不喜欢的话可以随意改,可以放心地交给美工改,至于逻辑代码则是编译好的我不用担心以后会被自己不小心改动了。或许这种设计与Page的Code-Behind编译有什么不同,关键就在于它强制规定了什么包含什么,包含多少个,而且这些被包含的控件的一些属性的默认值可能也在编译代码中,你看我上面的代码就没有指定<LoginForm:Submit>的value为“提交”或者“登录”,我的意思就是在编译代码中这个已经指定好了,这个指定好可能是指代码中为属性指定了默认值,甚至可能是那已经是一个派生类该派生类已经被指定了属性默认值。

2005年7月28日星期四

向导性搜索

所谓向导性搜索,就是在搜索过程中不断给用户Suggestion以及提供更多的有界输入(选项、范围)或者无界输入(文字)以不断所在范围。例如我们最常见的就是搜索结果通常会伴随着几个相关关键字,搜索引擎应该加上建议的操作让用户加上某个相关字或排除某个相关字,这样比起高级用户自己看相关字然后自己排除掉一部分(往往是排除,但你搜索目标比较偏的时候)要显得更加用户友善。

当然,我期望的向导不仅仅是这样。这里要提到我以前提出过的OO结构关字键理论,也就是对于任何一个关键字,它都有一个或者多个"基类"和非常非常多的"派生类",至于这里"派生"的关系和变成上的is_a关系是完全一致的。例如在你搜索StarWar的时候,首先搜索引擎会尝试识别基类然后提供给你作为选择,例如让你选择Movie还是Novel,然后你选择了Movie。这时候结果还是太多,于是搜索引擎提供主要的派生类,例如那么多集StarWar的名称,然后你再做选择。

不过我也很担心向导会存在一个陷阱,就是它的没完没了,最后可能陷入一个让用户觉得我提供了那么多信息让你进行过滤和重排,结果在搜索结果第一页还是没有我要的信息。这里我仅仅说是搜索结果第一页没有需要信息而不说没有结果,因为这个问题我也考虑过,所以在我认为的向导选择中,过滤的只是占少数,更多的是重排,然和向导中输入信息相关的浮上来无关的沉下去。

原来Google的PageRank Zero惩罚也是有终结的!

以前我一直想摆脱bbs.hsfz.net这个已经种了PageRank Zero惩罚的域名(我无非是在CooCooWakka留多了三个链接而已),不过今天突然发现它的PageRank竟然有5那么高哦(被惩罚之前是3)!哈哈,好开心啊,这样就可以把这个域名继续发展下去了。

今天去Windows Update的时候发现要正版验证了

以前就的那个正版验证控件是很容易通过的,VLK版也没问题。现在它要你装个新的,然后就通不过了,以后就只能通过Automatic Update来更新而不能够通过Web来更新,真是麻烦。希望快点有人有办法解决这个。(MS还不至于敢说不允许盗版用户更新,因为那样的话一旦发生新的病毒风波Windows就更惨了。)

2005年7月27日星期三

Blogger不懂超时,但坚持不懈……

原来给足够的时间Blogger.com它帮你上传完整个Blog还是没有问题的,它虽然不懂得什么超时自动重试,但在每到达它那个超长的超时限制之前它会坚持不懈的帮你上传,呵呵……

ASP.NET 是如何让 aspx 完全编译的呢?

我以前对这个问题一直持怀疑态度,因为.NET Framework里面就有很多TemplateControl处理类和方法挂上了Parse(或Parser)的字样,不过也有挂上Compile字样的。最近我确实测试了一次它是否完全编译:

我做了一个简单的纯asp页面:

<html>
<head>
<title>Now!</title>
</head>
<body>
<div><%=DateTime.Now%></div>
</body>
</html>

然后查看它的.dll,发现它自动生成了一个Page派生类,IRequiresSessionState也自动加上了,比普通的Page类多了一些双下划线开头的东西,例如两个双下划线开头的函数:
private void __BuildControlTree(Control __ctrl)
{
__ctrl.SetRenderMethodDelegate(new RenderMethod(this.__Render__control1));
}

private void __Render__control1(HtmlTextWriter __output, Control parameterContainer)
{
__output.Write("\r\n\r\n\r\n\r\n\r\n ");
__output.Write(DateTime.Now);
__output.Write("\r\n");
}

看来编译器会把html直接放到write的部分,中的逻辑再另外处理,例如Response.Write等效于等效于直接输出。至于它是怎么生成的,我还要研究研究才知道。另外这个功能不一定完全由CodeDom提供,可能CodeDom仅仅提供编译部分。Page类理论上是通过Parse来获取aspx里面的内容,然后把它们作为控件或者纯粹write出来的html添加到自己的内部,然而这时候得到的是一个对象的实例,不是一个类。假如由我设计ASP.NET,我会考虑是否存在可能性把一个实例转化为该类的派生类,或许ASP.NET真的是这样做的。

假如要把一个实例转化为一个类,这在Java或者.NET看来都并不难。例如在.NET里面,只需要把一个实例所包含的数据全部变为初始化数据放在类的初始化代码里面就行了,至于相关信息就放到meta-data里面,这个非常容易。如果.NET真的内置实现这种功能的东西,就一定要挖掘它出来。这意味着一种把逻辑缓存到dll的可能性,它拥有比缓存到内存更长久的保存性,同时因为它再次调用时无需再次编译所以这种缓存方式的效率也是绝对一流的。

2005年7月26日星期二

Community Server 进驻 hsfz.net

已经部署好了Community Server了,暂时部署在w3.hsfz.net。因为Benny将很多我不用的站点在ISA那里封了,所以要访问必须从校内访问(其实大家都是有办法访问校内网站的吧)。

看起来这个东西很不错(在使用上),集合了Blog、论坛、图片集,而且都有本来非常有名的组件。它强调的Collaboration(协作),所以不像很多过去的同类型产品一样都是鼓励大家多注册、多发表、多回复,而是引入了比较多的Restrict(限制),例如新注册用户默认状态是在管制下的(也就是发帖要通过审核贴子才显示,我已经更改为“50贴通过审核后自动脱离管制”),Blog也不是人人都自动有一个的而是只有管理员能开Blog并指定Owner的(这非常类似现在很多IT专项Blog,必须写申请给管理员证明你是该专项爱好者才能获取Blog)。至于图片集,我还没有测试过,好像允许匿名上传。

这个东西看起来对于“大学城网上通”的一期工程或许也有些用,它有论坛也有Blog和图片集。论坛适合于普通交流,Blog则是给通过审核的专栏作家发表的地方,图片集可以用来保存上传的图片。不过这样做也有一定的风险,因为不知道做扩展和数据迁移是否容易,如果我们的二期工程需要做大规模扩展或者开发一个全新的服务系统那就不一定容易了。

另外Community Server的分层设计上也很好。它不至于走Sharepoint那种纯dll设计(我承认,做纯dll设计的话开发和调试都比较辛苦,每次都要手动重新编译,需要改动UI也是很难的),它保留了aspx(其实Sharepoint也保留了,不过是存放在数据库里面,它自己有ISAPI Filter负责虚拟路径到数据库内文件的影射),然后把UI部分留在aspx/ascx里面。然而aspx/ascx并没有任何的详细代码,只有WebControl的引用,所有WebControl都封装在dll里,至于事务逻辑就都在背后了,很符合分层要求哦。

今天把Google AdSense装上了

在Blogger.com的控制面板见到大大个注册AdSense的标记,于是过去注册玩下,反正就算没钱也没所谓,我的Blog都是.NET有关的东西,出现的应该多数是.NET WinForm/WebForm控件广告(这是观测其它网站所得的),如果我见到好的控件我就会跑去看看,看看有没有什么优秀的地方值得我学习,或者干脆找找有没有“免费下载”,哈哈!

现在AdSense出来的还都是公益广告,可能Google还没有对我的网站做内容索引吧,那迟一点再回来看广告吧(很奇怪为什么是英文公益广告,难道我设置有问题)。

终于又成功发布Blog了

昨天晚上网络速度超慢,不知道干什么,发布时总是上传了一两个文件就停在那里了(Blogger.com的bot不懂得超时重试之类的东西)。今天下午尝试重新发布,估计网速没问题就没问题了吧,结果Blogger.com一直显示0%而我的ftp监视根本没显示有人登录!

这个问题我弄了一个多小时都解决不了(SFTP又总是不行,不知道为什么),于是跑去睡觉了。睡觉起来,怀疑是不是blogger.com会缓存一些有问题的目标ftp然后就根本不肯连上去,于是就断线重连。还是不行,那么难道是缓存域名?我把ftp由maxcellftp.3322.org改为maxcellblog.3322.org(暂时这两个域名IP一致而且我的ftp都接受),终于可以了。真不知道是Blogger.com太聪明懂得封ftp域名了还是它缓存一个ftp域名的IP太久了。

2005年7月25日星期一

改版改版~

现在总算弄到自己的ftp了,也就能够稳定维护这个blog了,而且还有hello+picasa这样轻松的发布信息和图片的组合,真的很爽。

现在我决定把这里改版了,改为我主要的blog,而wallop则主要是继续和别人message来来往往(我觉得wallop就是这点好,是一个能够自动适应投递宽度的mail-list)。以后我会把我在其它mail-list发表的东东(机密除外)也发表一份过来这里,让更多的人能够看到我的东西:)

2005年7月22日星期五

Windows Vista!

The next version of Windows, until now referred to by its code name Longhorn, finally has an official name: Windows Vista. 1个小时之前的新闻,刚刚碰巧进入news.google.com的美国版看到的。Vista是个好名字,强调View的意思,而且是Beautiful的,并且也是长远的或者广阔的View,并且这和Longhorn花费那么多功夫在Vision上也非常相配,不知道这个词是否能够迅速飙升为常用词(现在搜索vista还是一些都不相关的信息)。

2005年7月15日星期五

2005年7月14日星期四

ExileBoy

Exile,我希望用黑色加适当的高光作为主色调,好像Wind­ows Server Family那样(见过Windows 2003的安装界面吗?就是Windows XP的变成黑色为主调,但保留高光),同时用活跃的成色作为突出­色调。我也比较喜欢"葡萄式"广告里面那个成色的小人,所以决定­捏一个差不多的做为Exile的公仔,然后就叫做Exile Boy。

其实我一直很想画四格漫画,不过又没什么机会。我喜欢很久很久以­前Windows 95/98配的那个Microsoft Chat自动生成漫画的功能,因为仅仅Windows NT 4能够在IIS上加载Chat Server,所以应该很多人都没用过Microsoft Chat。我解释一下他的漫画功能吧,输入时还是像那个年代的普­通聊天室一样输入文字,或则选择一些文字描述的动作。如果是文字­形式查看,那就和普通Web聊天室没什么不同。如果选择漫画版式­,然后你从8个主角中选一个代表你,那么现时的将是4格漫画。大­概每两三条对话就集中到一格吧,这一格中出现了说话的角色,然后­头上有说话的冒泡,如果你选择了动作,那就是对应动作,不选择动­作的话也有些各种各样的小动作吧,反正那个年代的程序已经懂得避­免出现张张差不多的图片已经算不错的了。

我现在就是想试一下用.NET所谓的GDI+,做一个Exile­Boy的漫画制作工具:
1.这个工具能够轻松制作不同高难度动作的ExileBoy,我­希望好像3D软件那样我确定ExileBoy的关节点的位置,然­后软件就能够做出它的外形,当然ExileBoy仅仅是2D外形­。
2.这个工具内置若干绘图模块,而且不是简单的把某一个东西贴出­来,而是能够由创作者定义一些东西而工具本身又随机创作一些东西­,反正就是要有一定的随机性。
3.这个工具要支持插件。
还有很多其它的想法,例如要支持图层,而ExileBoy要能够­跨图层存在等(这要视觉效果才更好),不过要慢慢做。看看吧..­....我要先完成现在Quickling为主的Web项目,才­有时间来做这个,要慢慢等咯。不过之后我会把ExileBoy加­到Web上面去:)

2005年7月2日星期六

Tag with Map

能够好像flickr那样使用Tag,但Tag上去的不仅仅可以­是一个关键字,而可以是一个范围,或许是Map上的一个范围,那­样会怎样?想象一个支持Tag的Google Maps,呵呵......

最近喜欢模糊运算,所以有点拒绝不是0就是1的东西。如果你有时­间去看看模糊运算的有关法则,你就会发现它是我们现在学习的离散­数学运算的广义定义。例如x AND y就是max{x, y},那么对于0.5 AND 0.8来说结果就是0.8了。所以对于Tag,我也不喜欢它Ta­g死一样东西,而是最好说明一样东西对这个Tag的属于程度,取­值范围是[0,1]。

而Tag with Map就肯定会是这样--不可能有两个Tag准确的放到同一个L­at/Long(经度/纬度)上,那么一个Tag就应该是附设一­个范围。或者是若干个Tag就连成一个二维的曲线,至于曲线的高­度则由插值决定......嗯......看起来好像很复杂,我­只是觉得一个好的算法会运算得很好,让人在模糊集合中很快地找到­他要找的东西,并且是排好序的。(模糊集合的意思是,一个元素不­一定100%属于或者不属于这个集合,而可能是0.6属于这个集­合。)

2005年7月1日星期五

2 Ways Thinking In Ajax

至今来看,ajax的模式有两种,就是Google模式和.NE­T模式。

Google模式就是服务器仅仅接收xml和返回xml,其他一­切工作都是客户端做。开发的重点在于客户端,然后xmlhttp­仅仅用于发送和接收数据,服务器端则是仅处理数据的逻辑,如果把­xmlhttp看作"透明代理"的话,那么这个设计就是属于客户­端设计了。

.NET模式则刚刚好相反,虽然.NET说是把WebForm当­作WinForm开发,但它不是透明掉服务器端而是透明掉客户端­,为什么这样说呢?在你不需要JS的时候,你也可以当它是透明掉­服务器端,当你需要JS的时候,你就会觉得它是透明掉客户端了-­-它没有考虑过你要大量运用JS的情况。

Google模式看上去很容易实现,但当你实际操作的时候你就会­发现debug的痛苦程度!我甚至用js封装过专门的ajax库­了,这个库包括自动创建一个layer浮在最顶动态更新调试信息­(或者说是trace),但还是觉得非常痛苦!

.NET模式的痛处则在于JS--用到ajax怎么可能不是大量­JS,而这是.NET要避免的问题--.NET希望页面内的所有­元素都不是全局存在而是局部存在的,这样的设计才是正交的,如果­所有的逻辑都是拥有全局影响的权利,那么.NET建立的一切稳定­基础都会被打破,然而JS正是这样做着。.NET成功把HTTP­和HTML都对象化了,这依赖于以前ASP就有的Request­/Response模型和XHTML DOM模型。然而JS它无法对象化,除非我们能够创造一个JS CodeDOM。

现在Ajax的未来落在了Avalon的身上,Avalon本身­就是允许开发者用XAML描述界面并且用.NET描述逻辑,这对­于习惯XHTML+JS的Web开发者来说是件好事。然后它也做­到了客户端和服务器端语言的统一,而且是统一的CodeDOM。­而且MS可以采取一种很好的做法来让.NET开发者适应,就是开­发的时候服务器端代码和客户端代码还是混边,还是当作没有B/S­之分,然后把你希望在客户端执行的函数前面加一个例如[Clie­ntScript]标记那么该段代码就会在客户端运行,那时不是­很美妙的事情?而且这也符合MS的SmartClient战略哦­!