契丹--曾经的大辽梦

没有过不去的坎,只有回不去的段
  博客园  :: 首页  :: 新随笔  :: 联系 :: 订阅 订阅  :: 管理

     上文讲了标准化的重要性,本次就标准化实现着重讲一下。
     
      在项目组刚筹建时,我就建立了:C#代码规范、SQL脚本规范、数据库设计规范等。
      除数据库设计规范外,其他的两个网上有现成的,百度一下就行了。
      这个数据库规范可不什么第一范式,第二范式的东西,而是真正可执行的执导。
     
      首先,要对数据库内的命名有明确规定。比较简单,就是用英文单词来表示对象的意义,而英文单词之间用大小写分割,如货物编号就命名成GoodsID。
      我见过有用拼音缩写来做对象名的,这个的好处是门槛底,尤其对没过四级而又用拼音打字的同志们。但也存在不少问题,拼音缩写实在看不懂啥意思,货物编号就命名成hwbh,而海外编号缩写后也是hwbh。这个重复性的问题也很头痛,更有大侠想出后后缀的方法,hwbh1,hwbh2,简直不知所云,祸国殃民。

      用英文缩写也是个不错的选择,不过缩得太过分也有麻烦,像多批号英文应该是most lot,有位大姐(注意是女的)直接缩写成ML了。虽然没错,可感觉上总不舒服。

      我还见过不用大小写分割,用下划线。比如GoodsID变成goods_id。这样分也挺清晰的。但是让程序员每次都要多打下划线是不是不太方便啊(下划线要用shift+-才能出来的)。

      做好命名,我们开始对数据类型进行了统一定义。关系型数据库发展了30多年,数据类型可谓五花八门,但你做一个项目用是不可能用到所有数据类型的。尤其是现在的DBMS扩展了很多类型,像bit、bool、text等,因为我不想把数据库变成动物园,所以在项目中我将数据类型定了下来。
      整型只有int型一种;小数位的有Numeric(21,3)和Numeric(21,6)两种;字符串的Varchar(5),Varchar(20),Varchar(100),Varchar(200);日期只有Datatime。
      好了,没有了。这些类型足够用了,有些猛人连datatime型都不用(用varchar来代替)。
     
      这个数据类型一推出来,就有人提意见了,他认为Varchar(200)太小了,要用Varchar(4000)。
      说实话这是个相当不靠谱的意见,4000个字符相当于2000个汉字,2000汉字,你以为这系统要保存论文啊,再说了,DBMS规定表中列的总长度不应大于8K,也就是说你要有两个varchar(4000)的字段,这张表就很难再装一个字段了。
      不过直接拒绝是不太好的行为,至少项目经理不应该太霸道,做为接受意见,我决定将Varchar(200)改为Varchar(400)。当然了个别缺德的可以改成Varchar(201),我还不算缺德。

      为了更好的规定这些类型,防止个别不守纪律的人乱用,我引入PowerDesigner来做为数据库建模工具。这个工具除了做数据库建模外还支持UML,商业建模,组织结构,流程图等,就是界面一般,就功能来讲是比Visio和Rose还好的硬通货。

      PowerDesigner(后面简称PD)内中有一个Domain的对象(具体位置在菜单Model->Domain),这个东东就是把数据类型定义为一个对象。你可以为对象起名字,起外号也行。就这样,根据上面的规范,我定了8个Domain。从此规定Domain不得私自增加,钦此。

      在PD可以表内属性的格式进行定义,我将表内属性中的数据类型隐藏,只能通过Domain来选择。

      PD还有个功能,复制列(Replicate columns,具体位置在Table Properties窗口中Columns页框内)。就是你可以将模型中已有的列引入到另一个表中。引入列是不能修改的。如果修改源列,那所有引入列都会改变。简言之,就是继承列,这个继承还不许重载和多态。

      这可是有大大的好处的。比如你建张人员表,人员编号为varchar(20),而发票表要保存制单人,这里的人员编号为varchar(10)。问题出来了,当人员编号小于10位时,一切正常,当大于10位时,新建是通过的,但在业务中却走不通,理由是输入的字符超长。
     
      这个问题非常难搞,应该算到BUG类。但这类BUG要在特定条件下才产生,一般情况下看不出。而引入列可以避免此类问题。

      PD在建列时,除了可以给列写名称、定编码,还能给列加注释。而我的数据库设计规范中就要求所有列必须写注释。注释内容即在前台展示的label内容。通过代码可以到数据库中通过列的扩展属性找到注释的值。

      PD还可以,把触发器、存储过程、视图等等数据库内的东西都放到里面,还可以根据不同的DBMS来生产不同的SQL语句。总之这是个强得没边的数据库建模工具。SyBASE公司出的,我用的是12.5总共128M,生成的PDM文件还是XML格式的。现在最新的是15。

     主键历来是数据库设计的重点,不过也有人不建主键的,尽管我不知道他是出于什么动机,但不建主键的后果是很惨的,不能通过DBMS的视图来进行删除和修改,主索引不会自动建立等等,总之是不好了。
     那就建主键啊,这个和管市场一样,知道要管,关键要如何管。如果管得不好,把打狼的棒子都打到羊身上,那就失败了。从前两年看,我们伟大的祖国就失败了好几次。为了不让我们也失败,就必须分析以往的经验。

     最简单的主键就是GUID,这是个32位的字符串。
     优点:全球唯一随意生成。
     缺点:结构过长且无序。

     结构长说明其索引的空间大,空间越大检索时间越长。
     说到无序的问题,我们要说下索引的工作机制了,索引这个东西,为了快速检索而存在的,所以它里面的数据都是按顺序排列的(至于为啥按顺序排列,建议查看索引的原理)。
     现在有序的索引遇到无序的GUID了,索引是个一根筋,认为别看你外面多牛,到了我这一亩三分地,就得听我的。所以索引按照自己个儿的规矩来干,当新的GUID进来时,它会把所有GUID重新排序。索引这个做法就自身来看是没错(为了保持有序性),但重建索引的代价,就是性能的降低。总之一句话GUID做主键,会降低数据库的效率。

      GUID不适合做主键(这句话不是我说的,微软SQL开发组讲的)。

     那用标识列行不行,标识列是INT这也是我项目组讨论的问题。结果是不行。因为标识列是在数据保存后才生成的,也就是事后诸葛亮。事后诸葛亮就是没有事先好啊。
    
     问题来了,一张单据分别存到两张表——主表和明细表。两者用主表主键做关联。一般情况下是两张表一并新增的。我要把主表的主键写入明细表中,而事后诸葛亮,会在我写完主表后才知道主键的值,我再读一次返回值,再次赋到明细表的实体类中,再写入明细表。这样就是个麻烦事了,而且这个事后诸葛亮不能控制,或者说控制很困难。所以使用标识列也并不理想。

     那就自己做主键生成算法吧。这个好处是明显的,但是缺点也很明显,主要缺点是要增加开发工作量,每次还要获一次主键,而且万一控制不好,造成主键重复就更要命了。不过这是我能想到的最好方法了。以我的智商这个方法算不错了。哈哈

     主键的生成方式有了,为了更方便管理,为了数据持久层更加通用,所以我下令将所有主键都命名为IDS(ID是保留字,所以加个S)。
 
     数据库方面基本上就OK了。现在看看系统框架。

     系统框架比较简单,数据持久层+业务层+展现层。数据持久层的实体类是从数据库中生成的。别问我怎么生成的,数据库都给你了,你还生成不了吗?

     业务层都是代码,数据库对它基本没辙。

     由于我们在数据库中对列规定了Domain和注释,展现层就可以通过数据库来生成了,Domain生成控件,注释生成Lable,列的Code作为控件名,当然要加前缀(不同控件使用不同的前缀)。位置还是要手工调的。如果你不怕麻烦,可以把位置都写到数据库中。
     基本界面层和数据层不用太关心了。做好数据库设计,这两层基本上就算完事了,找个实习生,摆摆位置就算成了。

     现在我的团队可以把全部精力放到业务层了。业务层是所有标准化的重灾区,这里我决定放上一个猛人来解决这个问题。

篇后话:

     我的这套数据库命名法,只在SqlServer下成立,在Oracle下用就是找死,因为Oracle的列名全部是大小的,如果区分大小定,必须用引号。因此Oracle下基本都会用下划线来区分。如果你一定坚持用引号,也是可以的,如果你能忍受每打一个列都要加两个引号。
  
     其实这一套东西,很多人都知道,也有很多人就是这么做的。我把它讲出来是因为它是我项目标准中的一部分。

     从我做项目的经验中来看,现在的程序员对数据库的认识都不深,大部分都是用Hibernate,现在更好了有LINQ,连实体类都不写了。基本上大多数人会SELECT,INSERT,DELETE,UPDATE就行了。

     其实大家看一下,不管是当年的VB、PB、DELPHI,还是现在的JAVA、.NET、PHP,算上更早的DBASE,FOXPRO,再看看架构,单机版到C/S到B/S,还有B/S/S,这些技术不断更新,而后台的数据库却一直没变。说没变是指根,版本还是不断升级的。而我们做业务系统的核心操作就是增删改查,全是数据库操作。所以学习一下数据库还是很有必要的。再放眼未来,满天是BI、数据仓库,就是说数据库的路还长着呢!

     有时候想SQL和独孤九剑是一样一样的,只有几招(独孤九剑有九招,SQL只有四招),但每招的变化非常多,独孤九剑第一招总决试就有300多种变化(至于300多少,记不清了。等有空翻翻《笑傲江湖》),我想SELECT的变化不会少于这个数字。

     所以学会SQL容易,精通就很难(令狐冲学武奇才,学九剑还费了不少力呢)。再加上数据库自身处理机制(索引、优化、锁机制等)学习的内容非常庞大。

     有经验的朋友会知道,当系统发生效率低下时,往往是由于数据库造成的(人为SQL写的不优化)。所以建议程序员们学习一下SQL,多条技巧多条路。

 PowerDesigner 12.5官方下载地址 (15天试用版)http://download.sybase.com/eval/PowerDesigner/powerdesigner125_eval.exe 大小125 MB (132,006,349 字节)