导航

XWang's Thinking On Life And Technology

Sharing my minds, Under Creative Common License 3.0

一些废话

一些废话却还是要有个主题,从最近的技术大事开始好了

1. 华为爆出超低价出卖CDMA设备,MOTO更出价为0

事件起因:电信大力度建立基站,需要采购设备。公开招标,产生这样的结果。我们都知道华为很猛,但是猛到这个程度太牛了,MOTO就更像一个来搅局的,可惜啊,中国的基站设备,MOTO, 似乎离的比较远.

2. Google十周年

关于这个的报道满天飞,一个新的奇迹的诞生,不正是亿万IT从业人员梦想吗?不知道为什么,自己总是缺乏一种像Google, Microsoft核心价值观 - 服务大众的情怀,总是埋在自己小英雄的情节中,悲兮,技术之外,还是要多多参与下社会活动了,多多学着爱这个社会吧。虽然看起来, 做起来都是那么的困难. A little self-conscious

3. Chrome浏览器发布

也许是微软过于庞大,很难带来惊喜,干什么都比别人慢一步,这次Google发布浏览器,Microsoft却发布了一个Photo Sync, 难道说微软研究院都黔驴技穷到这个地步了,还有之前的Live Mesh, 也许是追逐微软的技术太久了,也许是我喜欢Chrome的快速与易用,总之,微软有点让人失望。微软的销售能力确实很强大,在广大的平民市场上短期内相信没有人能撼动,也许是我们要求太高,希望微软能够更有创新一些。IBM原总裁不是写过一本书吗,《大象也能跳舞》, 祝福微软一下 :)

4. 番茄花园作者被抓

相比之前QQ珊瑚虫作者被抓,这个被抓还真是一点都不冤枉,一个搞盗版的生活这么滋润,这么久确实是中国的特殊国情,对于中国国内的软件产业的发展百利,不过到了这个地步,大家还能不用Windows吗? 如果前些年,用Windows就要几百块, 我想现在自己肯定是一个Linux开发者了。

废话开始

转念一想,微软也挺累,服务器市场上要跟Linux, Unix, Solaris拼市场,新兴的UE市场上又要提高WPF的质量,Silverlight也还是幼稚儿,企业服务上,.Net始终限制于服务器的限制只能在中小企业市场有所作为。数据库上,现有级别上SQLSERVER还是相当的弱小. 娱乐上还要跟SONY,任天堂等厂商鏖战, 搜索还有Google这样的巨头。想想看,其实微软战线实在是太广了,每次项目会议的时候做投资决议的时候都会有更多的思考,每次看项目汇报的时候,都有那么一大一大叠的东西,鲍尔默即使是神,也会累的,更何况他也只是超级牛人,相比之下,也许之前的竞争对手是都太楞了点,现在的对手都是有很强大基础和很好的研发队伍的公司,微软再强,员工也有自己的想法,为什么非待在微软呢,更何况微软内部也是那么的官僚。微软会不会像之前的IBM一样成为一个官僚严重的机构呢?慢慢的成为一个平台公司。

我觉得会的,虽然这几年应该还行,过些年,也许就不行了,那Windows平台的这些开发者呢?熟悉Windows平台,精通API, .Net Framework. 到了将来是不是即将面临失业的危险,(说的我自己都有点害怕了 :( ), 微软每次都将技术细节封闭而不暴露,Windows 开发者都是左查API, 又看MSDN, 随时还弄弄第三方的控件,自己的思想和经验积累却是相当的少,又该如何?

这就引出了一个问题,技术人员的成长路线,传统的话题肯定是要做管理,似乎在中国只有做管理才有前途。不同的是,随着越来越多的国外公司进入中国,看起来很多公司都招高级的软件工程师了,似乎只有项目经理称王的时代已经过去了,技术路线上走的远与否还是有自己的选择的。然而到了更加高级的职位,竞争越来越激烈,相信各方面的能力都会是项目经理的一个衡量指标,对于高级的工程师,做好自己技术的深度,对于性能和质量有很好的把握就好了, 如果对于产品的商业价值有清醒的认识,我相信这个程度的高级工程师用不着担心自己的生活问题。

看着Google的成功,越来越相信自己创造价值的大小决定了舞台的大小,随着对社会的进一步深入接触,不再相信机会的重要性,更加相信实力的大小,到了这个能力,就进入了这个舞台,其他的一切就都会纷至沓来。

 

一点小想法,最近比较堕落,书都一星期没有看,说了一堆废话,实际行动无,惭愧一下。。。

奥运的是是非非

奥运前

大伙都盼奥运,等奥运,各大媒体不遗余力集中精力,怎么着都得看积极一面,票势全部 售光,一票难求等等,总之,要把奥运炒成香贝贝。大伙都要支持,不管真的是对自己有利没利,只要你来支持,你亏多少,跟别人没关系. 反而国际记者不能上自己的网站(伟大的防火墙),这样的事情避之而不报。

奥运中

辛苦 了咱们的运动员, 天天传捷报。各大媒体不遗余力,头条有金牌就爆金牌,没金牌就报现在金牌数稳居第一位,国内的没出成绩,就找个啥其他的亮点(埃蒙斯和他的美丽妻子),再 不行就弄个花边新闻,啥奥运女冠军情色等等。情势上,一律猛夸中国队,不管怎么养咱们干的奥运会肯定是最好的,先自己肯定要费心思整整,之后还要去各大外 媒要不挑出合适的,要不从某一篇文章中摘抄出来一部分,然后作为一部分证据。开幕式的大气,确实有很好的反响,整个的过程的各个方面说确实很好。但抹去的 地方真实而且更加珍贵,诸如开幕式假唱之流.

国内媒体与国际媒体的关注点显然不同,国际媒体更加关注菲尔普斯,Bolt这样的人类英雄还有自己本国的动态。另外还有花絮之类,诸如韩国的人均排行榜等等。

整 体上来说,从开始的外媒关注中国少,到后面的愈来愈多,奥运会确实为中国打开了一扇窗户:奥运期间,北京的天确实很蓝,北京的交通确实管制的不错,一点也 不拥挤,不变的是人民的素质还是在那,各位公交大哥大姐不会因为经过几次培训就会说一口流利的英语,各位小商小贩亦是如此。可喜的是,大伙至少长了见识, 有了一个开始。至于后来,等后来来了就自然知道了

奥运后

正如小说中一再叙述的那样,干了好事,出了成绩,就要开始论 公行赏了。于是各大电视媒体开始解密各大活动的准备工作,电视台的辛勤劳作,各大门户站点也开始争相说自己是某某数据的第一位了。真也好,假也罢,一切都 应该是这样来进行的,但是各位是否真的能吃到奥运后的大蛋糕吗?或者说这块蛋糕够大吗?有待时间来证明.

些许感想

开了窗户, 就会有阳光进来,然而阳光也不是对什么都有好处,原来那些在阴暗下生长的物质也许到了现在反而不太适合了。于个人来说,突然想起清华的校训: 行胜于言。

对于媒体与个人:搞宣传的就是搞宣传,不要因为他们的意识形态而影响了自己的主观判断.

对于个人与企业发展: 有实力的会因为更加开阔的天空而耀眼,而缺乏竞争力的却会有越来越小的生存空间。在现在这样的强国之路的意识形态下,走的好,走不好,实在是有大大的学问。

对于文化: 世界的融合必然带来思想的冲撞,而这正是文化的好机会好时机,相信这些年国史和哲学会伴随着经济有一定的发展。

不管怎样,希望自己健康幸福,家人平安,稳中又涨,偶有飞跃,足矣~

我眼中的Scrum和MSF

使用Scrum也有几个星期了,和之前难忘的MSF流程比较,有些感触,一起分享. :) 

概念:

什么是SCRUM?

SCRUM是一种流程,有人说是方法论,而他自己则说自己是框架。是新兴的敏捷过程的一种。

什么是MSF?

MSF也是流程, 传统的软件开发过程,广泛运用于微软内部流程改进, 分为CMMI版本和Agile版本。

 

他们都关注沟通,反思,需求,不同的是我觉得SCRUM更加人性化并且给出了具体的实施指南。MSF则更讲求框架,但是实际上可实施上并不够好,每一层都要求很严格,而SCRUM则将对质量的关注涉及到每一个方方面面,同时结合XP的开发方式,也很COOL哦。听说微软一些团队也开始使用SCRUM了。

关于MSF的流程在安装TFS时就已经安装好了,他的人员组成,文档模板都已经设计好了,需要的是具体管理人员在不同情况下的不同反应而已。

而对于SCRUM虽然没有具体的模板,但是一些技巧和解决问题的方式确实很值得提倡的,每日15分钟例会,Sprint, Story, 产品经理,发布计划,评估等等。SCRUM可以应用于各种团队的管理而不仅仅是软件开发。

从几个方面做一下比较好了

  需求 文档 编程方式 会议 测试 实施 团队 演示
MSF(Agile) 确定签字后无法更改 强调文档 传统方式,可结合TDD 自行安排 始终伴随 有实施部署阶段 沟通与改进 交付时
SCRUM 可以修改 弱化文档 TDD + XP 每天15分钟,方式不限, 2~4星期的Sprit 始终伴随 持续集成 沟通与改进,提倡固定的Team 2~4星期就会沟通演示,同时反思,修改下一步计划

图1: 我眼中的异同

当然了实际情况中,MSF也可以有持续集成,本身是一个不同的概念,我喜欢的是里面提供的实践指南,当然了有了实际指南,理论也不能丢,知之敏捷为何也很重要。感谢INFOQ和李剑的翻译。

有几段觉得很好玩的话一起enjoy一下, :o)

奴役式做法:对他们说,“你们今天可以给大伙儿干干杂活。倒咖啡、做按摩、清理垃圾、做午饭,一切一切大家今天让你们做的事情。”你会惊讶的发现 Joe 和 Lisa 在霎那之间就找出了有用的技术任务 )

本文右边的插图即是一本大伙都推荐的SCRUM书籍,  Go(中文版):

http://www.infoq.com/resource/minibooks/scrum-xp-from-the-trenches/zh/pdf/scrum-and-xp-chinese-version.pdf

另外CodePlex 上也有了SCRUM for TFS的模板: Go:

VSTS Scrum Process Template

Understanding Struct, 理解Struct

在.Net 中各种基本类型都是由struct定义,他与引用类型相有一些不同,有自己的特色,这篇BLOG由ECMA335中关于Value Type的定义开始

用Class定义的类型不一定都是引用类型,实际上,值类型就不是(例如:ValueType).用Class定义的ValueType包含了拆箱的值类型和关联的装箱类型. (ECMA335 Partition I, 8.9.7)

ValueType Has A Corresponding Reference Type 

  1. 当调用ValueType上的非静态方法时, this 指针是指向一个托管实例的引用,他会调用关联的装箱类型的方法.
  2. 值类型本身不支持接口,但是他关联的装箱的类型会.
  3. 值类型不能继承
  4. 装箱类型的基类不应该包含任何字段.
  5. 与引用类型不一样,值类型在创建实例时不需要调用构造函数. 默认他会把所有的字段根据类型设置为null或者0.

关于Struct类型使用的一般规则:

1. 不能定义无参数默认构造函数

   1: public struct Employee
   2:     {
   3:         public string Name;
   4:         
   5:         public Employee(string name)
   6:         {
   7:             this.Name = name;
   8:         }
   9:         
  10:         public Employee()
  11:         {
  12:         }
  13:         
  14:         public void Run()
  15:         {
  16:             Console.WriteLine("HI, I am {0}", Name);
  17:         }
  18:     }

错误信息: Structs cannot contain explicit parameterless constructors (Structs 不能包含显示的无参构造)

2. 不能初始化

   1: public struct Employee
   2:     {
   3:         public string Name = "Hello";
   4:     }

错误信息: 'Roger.Testing.Employee.Name': cannot have instance field initializers in structs (Structs中不能包含有初始化后的字段)

3. Read-Only状态不能更改

   1: static readonly Employee emp = new Employee("Roger");
   2:         
   3:         public static void Main()
   4:         {
   5:             emp.Name = "New Roger";
   6:             
   7:             Console.Read();
   8:         }

错 误信息: Fields of static readonly field 'Roger.Testing.Testing.emp' cannot be assigned to (except in a static constructor or a variable initializer)  readonly类型的Struct不能被赋值, 除非在静态构造函数或者变量初始化时可以修改

例子:

   1: static readonly Employee emp = new Employee("Roger");
   2:         
   3:         public static void Main()
   4:         {            
   5:             
   6:             Console.Read();
   7:         }
   8:         
   9:         static Testing()
  10:         {
  11:             emp.Name = "New Roger";
  12:         }

4. 不能继承

   1: public struct Manager : Employee
   2:     {
   3:         public string Title;
   4:     }

错误信息: 类型'Employee' 在接口列表中但不是接口

5. 可以继承无数接口

   1: public struct Manager : IComparable, ICloneable
   2:         {
   3:  
   4:             #region IComparable Members
   5:  
   6:             public int CompareTo(object obj)
   7:             {
   8:                 throw new NotImplementedException();
   9:             }
  10:  
  11:             #endregion
  12:  
  13:             #region ICloneable Members
  14:  
  15:             public object Clone()
  16:             {
  17:                 throw new NotImplementedException();
  18:             }
  19:  
  20:             #endregion
  21:         }

6. StructLayout

详细解释: http://www.cnblogs.com/happyhippy/articles/717028.html

7. 序列化Struct

   1: public static byte[]
   2:     RawSerialize(object anything)
   3: {
   4:     int rawsize =
   5:         Marshal.SizeOf(anything);
   6:     IntPtr buffer =
   7:         Marshal.AllocHGlobal(rawsize);
   8:     Marshal.StructureToPtr(anything,
   9:         buffer, false);
  10:     byte[] rawdata = new byte[rawsize];
  11:     Marshal.Copy(buffer, rawdata,
  12:         0, rawsize);
  13:     Marshal.FreeHGlobal(buffer);
  14:     return rawdata;
  15: }

8. 调用API

详细解释: http://www.yesky.com/165/1621165.shtml

Struct类型上的方法调用

   1: using System;
   2: using System.Collections.Generic;
   3:  
   4: namespace Roger.Testing
   5: {
   6:     public class Testing
   7:     {    
   8:         public static void Main()
   9:         {
  10:             Employee e = new Employee("www.xwang.org");
  11:             e.Run();
  12:             
  13:             Console.Read();
  14:         }
  15:     }
  16:     
  17:     public struct Employee
  18:     {
  19:         public string Name;
  20:         
  21:         public Employee(string name)
  22:         {
  23:             this.Name = name;
  24:         }
  25:         
  26:         public void Run()
  27:         {
  28:             Console.WriteLine("HI, I am {0}", Name);
  29:         }
  30:     }
  31: }

编译IL

   1: .method public hidebysig static void  Main() cil managed
   2: {
   3:   .entrypoint
   4:   // Code size       26 (0x1a)
   5:   .maxstack  2
   6:   .locals init (valuetype Roger.Testing.Employee V_0)
   7:   IL_0000:  ldloca.s   V_0
   8:   IL_0002:  ldstr      "www.xwang.org"
   9:   IL_0007:  call       instance void Roger.Testing.Employee::.ctor(string)
  10:   IL_000c:  ldloca.s   V_0
  11:   IL_000e:  call       instance void Roger.Testing.Employee::Run()
  12:   IL_0013:  call       int32 [mscorlib]System.Console::Read()
  13:   IL_0018:  pop
  14:   IL_0019:  ret
  15: } // end of method Testing::Main

大家可以看到

IL_0007:  call       instance void Roger.Testing.Employee::.Run()

实际上就是调用了开头所说的第一条. :)

和朋友讨论,说难道是每一次方法调用就会产生一次装箱而后调用方法吗?
正如开文所言,Struct的this指针会指向在内存中的装箱类型而后调用方法。

再看看WINDBG 中方法表的组成

WinDBG Run 方法代码

方法表中包含了RUN方法的调用,进一步证实了一个Associated Boxed Type的存在.

NaN(非数字), PositiveInfinity(无穷大), NegativeInfinity(无穷小)

NaN = Not A Number

读书时发现这个有趣的问题, 我们用一段测试代码来开始:

   1: using System;
   2: using System.Collections.Generic;
   3:  
   4: namespace Roger.Testing
   5: {
   6:     public class Testing
   7:     {    
   8:         public static void Main()
   9:         {
  10:             double a = 3.1415926;
  11:             double b = 3.1415926;
  12:             
  13:             Console.WriteLine("<- Comparing Values ->");
  14:             Console.WriteLine("Equals: {0}", a.Equals(b));
  15:             Console.WriteLine("==: {0}", a == b);
  16:  
  17:             Console.WriteLine("<- Comparing NaNs ->");
  18:             double c = double.NaN;
  19:             double d = double.NaN;
  20:             Console.WriteLine("Equals: {0}", c.Equals(d));
  21:             Console.WriteLine("==: {0}", c == d);
  22:             
  23:             Console.WriteLine("<- Comparing PositiveInfinity ->");
  24:             double e = double.PositiveInfinity;
  25:             double f = double.PositiveInfinity;
  26:             Console.WriteLine("Equals: {0}", e.Equals(f));
  27:             Console.WriteLine("==: {0}", e == f);
  28:             
  29:             Console.Read();
  30:         }
  31:     }
  32: }

结果如下:

image

我们看到NaN和NaN之间比较的结果是不一样的,但是为什么呢?都是NaN, 而且Equals和==结果不一样,关于这个的问题,在ECMA中有过特别的注明

Although two floating point NaNs are defined by IEC 60559:1989 to always compare as unequal, the System.Object.Equals requires that overrides must satisfy the requirements for an equivalence contract for operator.  Therefore, System.Double.Equals and System.Single.Equals return True when comparing two NaNs, while the equality operator returns False in that case, as required by the IEC standard.

虽然在IEC 60559:1989中定义两个NaN浮点数不相等,但是System.Object.Equals需要的重写必须满足操作的相等条件(an equivalence contract for operator)。所以, System.Double.Equals 和 System.Single.Equals 在比较连个NaNs返回True, 而相等操作符就遵循IEC标准返回False.

注: an equivalence contract for operator 代表

1. a == a // true

2. if a == b then b == a

3. if a == b and b == c then a == c

在这段话中,意为NaN和NaN对于CLS来说都是一致的,所以应该相等,这个本身是.Net特定环境的一个规则,对于其他语言并不一致

如果您看这个有点迷糊的时候,再看看Object中对于Equals中的实现(来自SSCLI20/CLR/BCL/System/Double.cs).

   1:  
   2:         // True if obj is another Double with the same value as the current instance.  This is
   3:         // a method of object equality, that only returns true if obj is also a double.
   4:         public override bool Equals(Object obj) {
   5:             if (!(obj is Double)) {
   6:                 return false;
   7:             }
   8:             double temp = ((Double)obj).m_value;
   9:             // This code below is written this way for performance reasons i.e the != and == check is intentional.
  10:             if (temp == m_value) {
  11:                 return true;
  12:             }
  13:             return IsNaN(temp) && IsNaN(m_value);
  14:         }

而IsNaN的实现则更加巧妙,大家一起欣赏一下

   1: public static bool IsNaN(double d)
   2:         {
   3:             //Jit will generate inlineable code with this
   4: // warning CS1718: comparison to same variable
   5: #pragma warning disable 1718
   6:             if (d != d)
   7:             {
   8:                 return true;
   9:             }
  10:             else
  11:             {
  12:                 return false;
  13:             }
  14: #pragma warning restore 1718
  15:         }

而d != d代表什么意思呢,我们看看NaN的具体值

   1: public const double NegativeInfinity = (double)-1.0 / (double)(0.0);
   2:         public const double PositiveInfinity = (double)1.0 / (double)(0.0);
   3:         public const double NaN = (double)0.0 / (double)0.0;

顺带我们也看了看PositiveInfinity和NegativeInfinity的值,也许你会觉得不可思议,为什么这样的值也是可以运行通过的,我们再深入一下,查看之前ECMA提到的IEEE标准: http://en.wikipedia.org/wiki/IEEE_754

在学计算机原理的时候,相信老师们都已经讲到了浮点数的表示方法,抱歉我也忘的差不多了, 我从IEEE标准中截取了对于NaN, PositiveInfinity和NegativeInfinity的定义,大家看看

image  From WiKI

  1. if exponent is 0 and fraction is 0, the number is ±0 (depending on the sign bit)
  2. if exponent = 2e − 1 and fraction is 0, the number is ±infinity (again depending on the sign bit), and
  3. if exponent = 2e − 1 and fraction is not 0, the number being represented is not a number (NaN).

对于NaN来说后面23位并不一致,而±infinity则都为0. 于是本文之初的结果现在看起来也是那么的自然了. :)

顺道提一下.Net对于三者之间的运算方法(来自 ECMA-335/ Virtual Execution System)

X rem 0 = NaN  // X 除以 0 = NaN
0 *  +infinity = 0 * -infinity = NaN 
(X / 0) = +infinity, if X > 0
   NaN, if X = 0
   infinity, if X < 0
NaN op X = X op NaN = NaN for all operations 
(+infinity) + (+infinity) =  (+infinity)
X / (+infinity) = 0
X mod (-infinity) = -X
(+infinity) - (+infinity) =  NaN

Have Fun, :)

Visual Studio 2008编译与运行DirectX 3D SDK Samples

下了Direct X 3D SDK运行玩了下, 碰到一些问题,有朋友问解决办法,Share一下. :)

运行环境

WIndows XP SP2 + Visual Studio 2008 VSTS + Microsoft DirectX SDK (June 2008)

大概会提示几个错误

1. 找不到 dxd3d9.h, dxd3d10.h

image

加入两个目录

image

2. 找不到dxerr.lib

image

加入Lib

image

3. 在运行时可能会出现找不到 D3dx9d_38.dll和D3dx10d_38.dll找不到的情况,