星星之火,终可燎原

在User Group展台前,各地UG Lead张牙舞爪

烟台俱乐部主席衣明志发表领奖感言

聚精会神观看北京.NET俱乐部演出的《大话西游之VSTS》话剧

够不着站起来,还够不着就上椅子,抢答问题的热烈场面… 

 

在TechED 2005 北京的会场上,微软技术俱乐部设立了一个精心设计的展台,供全国各地的User Group进行宣传,同时提供了彩页版的全国.NET User Group通讯供听众免费索取,而各地的UG Lead们在百忙之中抽取时间“站台”,负责向大家宣传各地User Group如火如荼的形式。在23号晚上的“微软技术聊斋”晚会上,UG Lead们欢聚一堂,在咖啡、红酒、音乐、奖品、话剧的氛围中相互交流,度过了一个难忘的夜晚。

回首两月以前,当开心与宝玉在MSN中讨论成立.NET User Group的时候,根本没有想到不到两个月,在全国已经成立起将近15个.NET俱乐部,而且每个月的活动也吸引了越来越多的当地.NET爱好者参加。真正达到了“星星之火,终可燎原”的目标。

在接下来的半年,开心将会继续专注于技术俱乐部的建设工作,欢迎大家把好的建议、点子发送给我(joycode # gmail.com ),我们期望在未来的一年当中,让更多的人享受到微软技术俱乐部带来的终身学习型气氛!

与 MSF 有关的两个问题

TechED 2005 上有个 Session ,主要内容是 MSF 4.0 的新特性及 Team System 的概况,其中讲师提了两个很意思的问题:

1、微软公司有多少个项目是按计划完成的?

大家刚开始猜答案的时候,还都是估计,我甚至想站起来使用一下 8/2 定理,结果大家的答案都不对,有人于是猜没有项目是按时完成的,最后终于有哥们指出这个问题的关键所在,此“计划”是“最初计划”呢,还是不断调整的“计划的最新状态”呢,因此这个题目的答案是:所有项目都是按计划完成的

这个题目带来的思考就是项目计划的动态性,项目的变化是天然的,所以计划也是不断更新的,很多人(包括我)在项目开始时仅使用 Microsoft Project 做个甘特图,就以为完成计划的制定了,这种思路一定要改变,PMI 中的项目管理也是不断在“制定”-“执行”-“控制”中循环进行的,是一样的道理。

要与时俱进。

2、微软公司有多少个部门在使用 MSF ?

这个问题问得大家有点懵,身后有个哥们好象是中途才进场的,没有座位,站在坐后,冷不丁地回答:没有一个部门在使用 MSF ,惹得大家一阵轰笑,出乎意料,讲师称人家的答案是对的。

讲师解释,在 MSF 出现之前,各个部门一直是按照各自的适合的模式来组织开发的,久而久之自然而然就形成了 MSF ,但是形成 MSF 并不意味着大家反过来要按照 MSF 的一些东西去严格执行,那一定是犯了教条主义的错误。

我见到一个有趣的现象,很多人在参加了 MSF 的相关培训之后,都希望找 MS 要各种各样的文档模板,其实在 MS 也很少存在统一的文档模板,只要能把问题(如 Spec)的几个关键要素的描写清楚,文档的用户能理解你的意图就可以了,何必要套模板呢? 对于模板的问题,可能很多人有不同的看法,包括在 RUP 、CMMI、ISO 9000 中都有非常多的文档模板,个人以为这种简单追求文档表面格式的统一并不能给软件开发带来很多的好处,“文档一大摞,Bug 一大堆”的情况并不少见。偏激一点,Windows、Office、Linux、Apache、Java 、Oracle 等等,那个是按照上述的开发流程搞出来的? Rational 虽然是 IBM 的东西了,也不多见 IBM 自己用这个东西。

要活学活用。

小程序:Word 文档批量查找/替换 (Visual Basic 6.0)

朋友接到其领导交付的一个体力活:要把好多个位于不同目录下面的 Word 文档里的敏感字眼替换掉,如“美国”换成“某国” …

对付文本文件的替换可以用 UltraEdit 来完成,暂时没找到有 Word 方面的工具,动手写了一个,简单实用,主要代码如下。

'--替换目录
Sub ReplaceDir(dir As String) Dim fso As New FileSystemObject, fo as Folder, fo1 as Folder, f as File Set fo = fso.GetFolder(dir) '--初始目录 For Each f In fo.Files If UCase(Right(f.Name, 4)) = ".DOC" And Left(f.Name, 1) <> "~" Then ReplaceFile (f.Path) End If Next For Each fo1 In fo.SubFolders ReplaceDir (fo1.Path) Next End Sub '--替换文件 Sub ReplaceFile(fileName As String) Dim doc As Object On Error Resume Next Set doc = GetObject(fileName) doc.Visible = False For i = 0 To UBound(aText) doc.ActiveWindow.Selection.Find.Execute "要替换的词", False, False, False, False, False, &_
               True, 1, False, "被替换的词", 2, False, True, False, False
         '稍微修改一下,可以实现多个词语的替换
     Next

doc.Save
doc.Close
Set doc = Nothing
End Sub

Atlas的整体架构概述

下面是Shanku NiyogiNikhil Kothari在PDC 2005上演示中展示的Atlas的整体架构图


(偷自Nikhil Kothari的PPT)

Nikhil Kothari,Atlas的设计宗旨不是要成为普普通通的AJAX类库,而是成为一个跨越客户端和服务器端开发以及整合两者交互的一个整体应用框架(end-to-end application framework),它允许开发人员,既可以用XML声明的方式,也可以用脚本编程的方式,很快地集成组件,并且使得脚本功能与ASP.NET应用的集成既整洁,又不让人觉得唐突。

Atlas提供了一个客户端的框架和服务,主要包括
1。浏览器兼容层,把浏览器之间的差异封装出来,以利于其他层次的功能的浏览器独立性,目前支持IE,Safari和Firefox

2。脚本内核,包括了一个Javascript的整套类体系,允许你使用标准OOP里的构造,譬如,命名空间,类,接口,继承,枚举,代理(delegate)等等。目的是要提供一个机制把数据,逻辑和行为封装成类,使得开发人员可以象和其他编程语言一样来做脚本开发

3。基类库,受.NET框架启发,提供了StringBuilder, Debug, Event,和 IDisposable等方便的基础类型,同时通过WebRequest, WebResponse类提供了一个基于XMLHTTP 的客户端networking层,在上面可以通过MethodRequest 与aspx和asmx等服务端服务进行交互。也提供了序列化,特别是JSON 序列化器。该类库也提供了可以和服务器端相应服务集成的Profile 和认证服务

4。组件模型和UI框架,引进了可以自描述本身对象模型的组件的概念,这些模型可以参与一个顶层的Application类管理的生命周期机制,可以通过以声明或编程的方式建立,可以通过绑定以及事件的形式来传输数据和交互。UI框架提供了与DHTML UI元素相关的控件,以及如何给这些控件附加行为的机制,譬如象Drag/Drop以及对输入控件数据的验证等等。

5。控件和组件,提供了象计时器(Timer)和计数器(Counter)这样的组件以及象ListView和地图控件等的控件

Atlas也提供了相应的服务器端基础设施,
1。服务器控件框架,定义了一个新的控件ScriptManager来管理传回到客户端的脚本以及由服务器控件生成的XML-脚本标识。服务器控件也可以通过实现 IScriptComponent来参与请求处理,同时,还提供了与客户端组件模型类型相对应的服务器端对象

2。网络服务桥,允许客户端脚本访问普通的网络服务(asmx)以及Indigo风格的服务(svc),也可以直接访问网页内声明的WebMethod,这是通过象下面这样的类似声明

<script src=”MyService.asmx/js” />

由服务自动产生javacript代理类来实现的,同时提供了实现JSON协议调用服务器端服务的基础设施

3。应用服务桥,通过网络服务桥提供了ASP.NET的几个应用服务,譬如可以通过成员服务做用户认证,以及通过Profile服务访问/更新用户数据等

详见Nikhil Kothari的blog以及下面两个ppt

Atlas Architecture Overview

PRS312 ASP.NET: Future Directions for Developing Rich Web Applications with Atlas (Part 1)

PRS420 ASP.NET: Future Directions for Developing Rich Web Applications with Atlas (Part 2)

俺这两年

鹧鸪天
黄庭坚 
黄菊枝头生晓寒。
人生莫放酒杯干。
风前横笛斜吹雨,醉里簪花倒著冠。
 
身健在,且加餐。
舞裙歌板尽情欢。
黄花白发相牵挽,付与时人冷眼看。

在为《程序员》杂志写的纪念性文章《.NET这五年》中,为了显示自己有些学问,找了这么一首词作为序子。甚至在拟稿的时候,欺骗太太说这是我自己填的词,惹来崇拜的眼神。

其实当初选这首词,只是看中了其豪迈的风格,那种“付与时人冷眼看”的境界最让我艳羡不已。幻想自己的老年,也会如此放荡不羁,快意江湖,那是何等的境界。

2002年2月份,当时开心还在北京一家公司担任着架构师的工作。由于工作关系,会经常上微软的网站,很偶然间看到微软要举办MVP评选的消息,那颗跳动的心立即不安分起来,决定勇敢的跳出来试一下,于是怀着惴惴不安的心情在线提交了自己的申请表。接下来的时间,一直在怀疑与紧张当中度过,不晓得自己会不会中选,因为这毕竟是一个“头衔”非常大的称号。日复一日的等待,到最后逐步恢复平静,毕竟这种希望是太渺茫了。就在自己已经忘记这件事情的时候,却在某天早上,收到一封电子邮件,通知我已经当选了Asia MVP,而且这个称号在全国仅仅有20余位,心情之激动,恨不得让全世上的人都知道。当然,第一件事情是告诉了我的女朋友(我相信各位朋友也是第一次时间把这个消息告诉了自己的另一半吧?)。接下来,我的老板也得知了此事,在我没有任何要求的情况下,欣喜得为我加了工资,并且准我三天假,去参加上海的亚洲MVP峰会。

而后在4月份,怀惴着激动的心情,在微软的赞助下,平生第一次坐上了飞机(好象那次是东航,呵呵),平生第一次来到了上海,平生第一次进入了微软的Office,平生第一次与那么多老外在一起交流,这些平生的第一次至今让我激动不已。而这其中最让我兴奋的是见到了一些原来只是在网上听说过的微软的朋友:唐骏、华宏伟、刘润、王建硕、Wendy Fan等(那时候没有见到Grace以及Eddie)。并且身临现场的听到了他们的激情演讲,虽然现在,自己也身临现场听过盖茨及其它微软高层的演讲,而且自己也在微软的各种大小活动中做过演讲,但时至今日,当日那种身临现场的激情仍然在撞击着我,使我至今难以忘怀。事过境迁,唐骏已经去了盛大,而王建硕也去了eBay客齐集担任CEO。还好,大部分人仍然都有BLOG,可以了解他们的最新行踪。

大约是在9月份,Asia MVP的称号被升了一个级,成为了Global MVP。虽然后来的全球峰会因为Visa的问题,而没有参加成,但这是平生第一次出国的机会,却是因为MVP而提供的。真正第一次出国,是在今年四月份参加在新加坡的亚洲MVP峰会,虽然已经不再是MVP了,但之所以可以参加此次峰会,也是因为“曾任”MVP,所以才能够有此机会参加此次盛会。MVP给了我太多第一次。
接下来的第一次是在2003年的8月31日,至今让我难忘。那天晚上,我接到了微软北京的一个电话,打电话的人自称是曹严明,问我是否可以参加微软的一个短期工作。我欣喜的答应了此事。随即马上上网,在搜索引擎中输入“曹严明”,哇,原来是微软中国的首席架构专家,还曾经在Redmond编写过SQL Server以及Exchange,他竟然亲自给我打电话了。第二天,是9月1日,我来到了微软的Office,结果正好开全体员工大会,原来那天是Tim Chen第一次对微软中国的全体员工训话,而我也有幸代表MVP参加了此次活动。

接下来的两个月时间,一直在曹严明、胡锐等“牛人”的带领下,做了一些短期的项目。而后,在11月13日,微软另外一个部门的领导找我谈话,问我愿意不愿意加入微软担任v-工作?终于我可以成为微软的员工了!!!心情又开始激动起来。但接下来想到的是,我进入微软工作后,可否仍然继续做MVP?赶紧打电话向Grace求证,得到了肯定的答复。

终于在微软偌大的Office当中,有了自己的位置。在布置自己那一亩三分地的时候,除了必备的资料等东西外,我还把MVP的奖杯、奖状等放在了桌上最显著的位置。时至今日,此习惯仍然不变。

在2004年10月1日,中华人民共和国五十五年华诞,我进入了开发合作部,开始担任推广.NET的重任。并且在那年的TechED上,开心第一次登上了微软的讲台,可能有些朋友当时在广州及北京会场上听过我那“丑小鸭”式的课程,但大家不知道的是,为了准备那门课程,开心在广州中国大酒店的房间当中,一个人面对卫生间的镜子,从午夜十二点到凌晨四点,苦苦练习了四个小时。

而现在,即将工作满一年,昨夜夜不能寐,仅写下此篇文章,作为纪念。这些连续的“质变”让我的一生发生了改变,如果大家参加过2004年的峰会,那么可能会在开场的录像上看到开心泪眼迷离的说了一句“MVP改变了我的一生”,此乃肺腑之言也。

 

PS:前段时间BLOG圈内流行一个“说出你的怪僻”的游戏,开始游戏的人出一个题目,在自己的blog上写下答案,然后把题目丢给另外五个人,在文末附上这五个人的连结,并且到这些人的留言版上留下:“哈哈!你被贴了。”(哈哈是我自己加的)。这五个被tag到的人,在自己的blog注明(并附上连结)是从哪一个blogger那里传来的题目(这时候“引用”功能就很好用),然后写下答案,再去贴另外五个人。如此继续下去。现在我开始点名,希望大家可以继续

  • 邹欣(关心):  微软VSTS产品组的,我对其进入微软的面试过程非常感兴趣,希望可以分享一下。
  • 孙展波:展波老大在TechED上的Fans大家有目共睹,我希望听到他对于中国软件产业从业人员(最主要的是他的Fans)的一些看法,而不只是Avalon,Avalon…
  • 郑子颖:  ATC上海分院的,超级自恋狂,厨艺大师,我对其当年从GTSC转去ATC这段时间的想法非常感兴趣
  • 思归: 老大哥,我希望听听他是如何学习的,在这个年龄段当中,如何能够深入的学习技术,而且可以学得如此精,这让我非常佩服
  • Kaneboy: 曾经看过你写的《从服务员到程序员》,后来你删掉了,说准备在写回忆录时重写,我现在催熟你的回忆录,希望尽快看到你的成长之路。

生命的尊严与工作的压力

生命的尊严与工作的压力,哪一个更重要?赵传的歌曲一遍一遍在宁静的夜里面质疑着我。是呀,哪个更加重要?

相信每位从事IT业的朋友都会有类似的疑问。无疑,在圈外人看来,我们是非常幸福的,拿着高薪,出则飞机,住则五星级酒店,还经常会有出国的机会。可是世上没有白来的午餐(晚餐?),得到这么多,肯定也会有相应的压力提供给你。

好久没有写过BLOG了,即使心有所得,也似乎找不到时间。答应《程序员》杂志社的稿子也会一周一周的往后拖,原因就是没有时间。而“时间是海绵的水”,只是我没有时间在那儿找到海绵、判断海绵中是否有水、腾出手来挤海绵。生命似乎只是在旅途中,飞机、酒店、公司、家。

曾经幻想过那么多与家人相聚时,如何其乐融融。但在家的时候,却开始发现由于工作的压力开始出现了脾气,开始变成了一个急性子的人。关爱的眼神,也抵制不住发泄的冲动。而后伤心、后悔,却找不到补救的办法。

男人应该顶天立地,但既然没有一点空隙,留给你的也只是天地之间的压力。工作是为了生活,而生活是为了什么?有时候开始有那么一丝迷茫,发现回到了大学时代,空闲时我们会迷茫,但压力大的时候一样会有迷茫。

也曾经幻想年薪如何如何了,我会如何如何,但其实又如何?

其实我热爱我的工作,这是我从小就渴望做的工作,我在工作当中享受着成功的喜悦,在别人的眼神当中得到自己的成功,在父母与长辈中对自己的夸赞中沾沾自喜。也曾经在无人的夜里面,通过搜索引擎,查看别人对自己的评论,知道自己的工作对于大家还是有意义的。这时候,我感觉自己活着,值!

我也热爱我的生活,父母赋闲在家,为了家务而劳动。父亲虽然没有念过初中,但仍然会一遍一遍去读我书的前言。母亲也会在其朋友的孩子面前称赞,好好学习,将来像你哥哥一样。爱妻娇羞可爱,成天像个孩子似的缠着我,无论我是在做什么,她都会跟在我身边,尤其是我出差回来,她散发出来的那种由衷的喜悦。我享受着生活,享受着家人赋予我的天伦之乐。

但繁忙的工作,开始让我无法去承担一家之主的责任,家里面的大事小事只能让父母及爱妻去打理,甚至我根本无法确定我的行程,今天我还在上海,后天可能就会去福州,而在这之中,老板一个电话,我可能会出现在另外一个陌生的机场,住在另外一个陌生的酒店。我甚至不敢确认自己一周后的某一天会不会在某地,就像那断了线风筝一样,随着风飘动…

To Be or not to be,这是一个问题,在飞机上,我一遍一遍的思考自己的现在,思考自己的未来,思考着家庭与工作,哪个才对于我更加重要?

而现在,我终于有了自己的决定,就让一切follow my heart。

我的兄弟姐妹们,你们呢?

 

 

 

关于DLINQ的争议

DLINQ宣布后,网上有很多争议,其中以Paul Wilson的意见最有代表性

Linq is Really Cool — But DLinq is a Big Mess

他指出,虽然DLINQ还是早期预览版本,但这已经是微软第三次尝试O/R Mapper了(之前有过ObjectSpaces的2个版本)。没用过O/R Mapper的人也许会认为DLINQ是个很大的进步,但熟悉O/R Mapper的人,却发现DLINQ问题多多,主要包括:
1。这是个基于属性(attribute-based)的方案,比外部映射文件的方法为差,连DLINQ自己文档中说到的non-intrusive的目标都没达到
2。目前只支持SQL Server
3。过分复杂,开发人员要熟练掌握/使用,需要了解的东西很多
4。对存储过程支持不足,现有的支持也要求开发人员写很多编码
5。功能有限,没有服务器端的分页支持,还不支持many-to-many relationship以及inheritance,没有WinFS/OPath集成。。。。

代码生成器 SQLMetal

随LINQ一起来的工具里,有个Entity Class Generator Tool,叫SQLMetal,能连接到数据库直接产生跟数据表对应的Entity Class,就象上个帖子里的例子一样

SqlMetal /server:(local) /database:DLINQ /delayfetch /pluralize /namespace:LINQ.Examples.QuickStart /code:User.cs

也可以先生成一个Schema XML文件,譬如

SqlMetal /server:(local) /database:DLINQ /pluralize /xml:User.xml

对应上个贴里的Users表的XML是这样的

<Database xmlns:xsi=”http://www.w3.org/2001/XMLSchema-instance” xmlns:xsd=”http://www.w3.org/2001/XMLSchema” Name=”DLINQ”>
  <Schema Name=”Dbo”>
    <Table Name=”users” Property=”Users” Class=”User”>
      <Column Name=”LogonID” Type=”System.String” DbType=”NVarChar(20) NOT NULL” Nullable=”false” IsIdentity=”true” />
      <Column Name=”Name” Type=”System.String” DbType=”NVarChar(40)” />
      <Column Name=”Password” Type=”System.String” DbType=”NVarChar(20)” />
      <Column Name=”EmailAddress” Type=”System.String” DbType=”NVarChar(40)” />
      <Column Name=”LastLogon” Type=”System.DateTime” DbType=”DateTime” Nullable=”true” />
      <PrimaryKey Name=”PK__users__09DE7BCC”>
        <Column Name=”LogonID” />
      </PrimaryKey>
      <Index Name=”PK__users__09DE7BCC” Style=”CLUSTERED” IsUnique=”true”>
        <Column Name=”LogonID” />
      </Index>
    </Table>
  </Schema>
</Database>

你可以修改其中内容 (但居然无法修改生成的property name??),然后再运行SQLMetal来产生编码

SqlMetal /namespace:LINQ.Examples.QuickStart /code:User.cs User.xml

注意,生成的Entity Class是个partial class

public partial class User : System.Data.DLinq.IChangeNotifier
{
  //….
}

里面是对应数据表字段的变量和property们,你可以在另外的文件里定义该类的操作,譬如

public partial class User
{
  public void Test()
  {
     Console.WriteLine(“User:Test():” + Name);
  }

        //…..
}

这样,即使你用SQLMetal重新生成Entity Class文件,也不会影响你定义操作的文件。将来IDE大概会支持,或者顶多在Build过程中多加一步

DLINQ练习

以前做过一个NHibernate练习,这里用DLINQ重新来过

 

想试的话,也许需要改动连接字符串,可惜上面的程序在8月份的CTP上不工作。出錯信息是

Unhandled Exception: System.TypeLoadException: Could not load type ‘System.INullableValue’ from assembly ‘mscorlib, Version=2.0.0.0, Culture=neutral, PublicKeyToken=b77a5c561934e089’.
   at System.Data.DLinq.SqlClient.QueryConverter.IsConstNull(ConstantExpression expr)
   at System.Data.DLinq.SqlClient.QueryConverter.VisitConstant(ConstantExpression cons) in c:\PdcBuild\query\DLinq\Engine\Converter.cs:line 500
   at System.Data.DLinq.SqlClient.QueryConverter.VisitInner(Expression node) in c:\PdcBuild\query\DLinq\Engine\Converter.cs:line 102……