简单声明一下。
在http://www.cnblogs.com/progame/archive/2004/06/27/19062.aspx的帖子中,反驳了我的观点,无可厚非,各人的观点不同嘛。不过,我想说明一点:我是搞快速开发的,是在保证工程质量前提下进行尽量的快速开发,所以有一些观点是涉及到一些技巧的,但也这些技巧与观点均建立在面向对象的思想之上。
对于 progame的txtName.Text = Employee.Name & “”写法,我没有任何反对意见,这倒是一个不错的写法。
不过,从纯对象角度来说,“NULL并不表示这个属性没有,而是说这个属性暂时“未知”,比如说员工表的出生日期字段,用default?1900-01-01?还是1990-01-01? 难道这种默认值就不需要前台程序判断?”,如果是这样理解属性为空的概念也未尝不可,但是这样,在进行业务建模时,就应该将有Null值的属性列采用虚类进行描述,可以参考一下对象/关系映射--继承模式中指出的One Inheritance Path One Table模式,在这里模式中,虚类是不能映射到表的,原因就是我们用的是关系型数据库,而不是对象型数据库,在关系型数据库中,一般不会出现可变化的虚表,当然也可以从其它手段进行模拟,不过,这如同用C来写对象化的编程一样,毕竟要麻烦一些。
上面说的员工表的出生日期字段,用1900-01-01还是1990-01-01,我认为既然站在了对象的角度来看,就不应该考虑作为对象的“员工的出生日期”的是1900-01-01还是1990-01-01,属性本身是不应有指定的数据格式,因为属性只是一个描述,像1990-01-01这类格式字段,本身也是作为“出生日期”的属性信息而存储于数据库之中的。而且,默认值似乎也不会影响到实际应用程序中的操作,可能 progame老兄习惯于使用数据绑定操作进行数据库的操作,所以会遇到默认值选择什么比较好的问题。但请稍注意一下,属性的默认值,不一定是直接用于数据呈现而用的,它的作用是填充数据库中属性里残缺的部分,在关系型数据库与外部程序连接时,如果少了数据库的默认值,它在直接访问时的逻辑上更大的情况不是表示出了不存在,而表示出了未知。
eg. 在员工表中,假设,家庭住址为空,那么在此情况,如果应用程序请求员工的家庭住址的值时,数据库直接返回一个空标识,这时,在应用程序中,如果有一个对象接收到此空标识时,这个空标识作为object时,是null值,对象引用为空值,表达的直接逻辑就是不存在,而不应该是未知。按我的思想,一般的情况下,你不应该能够进行如下形式的声明(伪代码说明):
string str = null;
object o = (object)str;
上面的代码对一个string类型的对象进行装箱操作,但实际上,对于object本身来说是一个引用型,当对str进行装箱后,它实际上是对一个null进行了装箱操作,所以这是不应该能够实现的代码,但在.net的C#代码中,为什么编译能够通过?
在CLR中,是如下的操作:
.maxstack 1
.locals init ([0] string str,
[1] object o)
IL_0000: ldnull
IL_0001: stloc.0
IL_0002: ldloc.0
IL_0003: stloc.1
请注意上面的颜色标识部分,([0] string str, [1] object o)发现了什么?对,[0]string str,0长度大小的string,这是CLR的自动转换,并且,还可以看到[1] object o,这是外部进行的装箱,也就是说,这里并不是类型转换,而是外部的一个包装而已。这样,应用程序中实际执行的代码与数据库中提交过来的数据,实际上已经被“污染”过了,这是无法实现高效的O/R映射的。因为在关系数据库中有数据类型的概念,其中分开了空值与0长度大小的概念,就关系型数据而言,空值确实是表示不存在,因为它返回的不是一个string的数据类型的空值,而返回的就是一个Null值。
在必要的情况下,如果非得进行空值操作,建议对数据库的返回的空值,进行泛型改造。
在数据库中,我觉得应该设定默认值的问题,并不是谁说了就谁是对了,当然,我的观点或理论上的理解也可能是错误的,如果能够指正,我当然也很高兴,毕竟这也是一种进步。