SUMTEC -- There's a thing in my bloglet.

But it's not only one. It's many. It's the same as other things but it exactly likes nothing else...

  博客园 :: 首页 :: 新随笔 :: 联系 :: 订阅 订阅 :: 管理 ::
  207 随笔 :: 19 文章 :: 1637 评论 :: 14 引用

前一阵子之所以有一定的牢骚,主要是因为最近总能遇到一股Destruct的力量。什么是Destruct呢,就是construct的反义词呗。第一次对这个词感兴趣,是在一篇说微软和对手竞争的手段:对一个既有的不属于自己的标准,创造出一种跟他很像,但又不是一回事的标准。此过程就是对既有标准的一种破坏,就是Destruct。相信大家都知道我说的是什么事情了吧,就是当时的Java标准之争。

这种自行创造出一套边缘体系,与现有的体系平行却完全不受控制的东西,都是极具破坏性的。标准如此,开发也如此。最近碰到的就是这么一种破坏,能够把人搞得狠抓狂。
比如说吧,有一个配置相关的类,该类对一堆xml做解析并转换成配置对象。这堆配置文件当中有一个缺省配置,所以其他的配置里面没有的描述,都相当于直接使用缺省配置。这个xml的结构本身有一个规定,即:所有开关量、数值等,写在配置节点的属性(attribute)当中;所有需要显示出来的Html,写在一个子节点当中。具体一点的例子是:
<UserRole name="$default" canCreate="false" canView="true" enabled="true">
  <Description><![CDATA[这是一个<b>未知用户</b>!]]></Description>
  <Hello><![CDATA[系统出错,请联系管理员!]]></Hello>
</UserRole>
<UserRole name="user">
  <Description><![CDATA[这是一个<b>普通用户</b>!]]></Description>
  <Hello><![CDATA[{name},您好!]]></Hello>
</UserRole>
<UserRole name="admin" canCreate="true">
  <Description><![CDATA[这是一个<b>管理员</b>!]]></Description>
</UserRole>

在这么一个系统下面,假设我们有如下代码:
UserRole role = user.Role;
Debug.WriteLine(role.CanCreate);
Debug.WriteLine(role.Hello);

我们可以预期,如果是普通用户,那会返回"false"和"{name},您好!",而如果是管理员,则分别返回"true"和"{name},您好!"。这么设计的最基本原因,是为了可以很方便的修改一些默认的配置,例如欢迎语。可以想象,如果我们修改$default的Hello字节点,就可以很方便的更新大多数用户类型的显示方式,同时也不会影响到那些有特殊显示要求的用户类型(比如说老总可能喜欢看"{name},恭喜发财啊!")。

稍微思考一下就会发现,如果在子节点上定义属性,现有的体系是绝对不支持“缺省配置”的。即$default配置上面的这些属性是不会被其他配置对象获取到的。具一个具体的例子,有一天程序员Murderer在配置里面加了一些修改:
<UserRole name="$default" canCreate="false" canView="true" enabled="true">
  <Description><![CDATA[这是一个<b>未知用户</b>!]]></Description>
  <Hello><![CDATA[系统出错,请联系管理员!]]></Hello>
  <Salary queryPage="http://mycorp/newpath/salaryquery.aspx" controlRight="none"><Salary>
</UserRole>
<UserRole name="user">
  <Description><![CDATA[这是一个<b>普通用户</b>!]]></Description>
  <Hello><![CDATA[{name},您好!]]></Hello>
  <Salary queryPage="http://mycorp/oldpath/salaryquery.aspx" controlRight="view"><Salary>
</UserRole>
<UserRole name="CFO">
  <Description><![CDATA[这是一个<b>财务总监</b>!]]></Description>
  <Hello><![CDATA[{name},您好!]]></Hello>
  <Salary queryPage="http://mycorp/oldpath/salaryquery.aspx" controlRight="view, pay"><Salary>
</UserRole>
<UserRole name="admin" canCreate="true">
  <Description><![CDATA[这是一个<b>管理员</b>!]]></Description>
  <Salary queryPage="http://mycorp/system/salarycontrol.aspx" controlRight="all"><Salary>
</UserRole>

这个修改可真是惨了,系统出现错误,因为配置错了,oldpath的目录不存在。其实这是该页面在旧系统里面的位置,新系统改为newpath了。原来一直使用这个配置的人会很奇怪,明明$default里面已经改过来了,而所有用户除了管理员的之外,都应该是访问同一个地方啊。为什么呢?
原因就在于子节点的属性无法继承缺省配置!而这么修改的程序员Murderer也就是图了方便:原来这个配置可能是在另外一个没有“缺省配置”特性的xml配置系统里面的,现在需要做一个合并,结果不加修改就配置过来了。同时把读取该属性的代码也一并拷贝过来,比如说:
public string SalaryPage
{
  get{ return _node["Salary"].Attributes["queryPage"].Value; }
}

作为对比,原始读取Name属性的代码可能是类似这样的:
public string Name
{
  get{ return GetAttribute("name"); }
}
private string GetAttribute(string attributeName)
{
  XmlAttribute attribute = _node["Salary"].Attributes[attributeName];
  if (attribute == null)
  {
    if (this != _Default) {return _Default.GetAttribute(attributeName);} else {return null;}
  }
  else
  {
    return attribute.Value;
  }
}

可以想象,其他的属性比如CanCreate、CanView也应该是类似的,属以同一个体系,具有同样特性的东西(比如有缺省配置的特性)。而由于SalaryPage的加入,导致了整个体系的崩解——那些原有的代码似乎没有了存在的意义。原因很简单,这些原有的代码之所以存在,就是为了保证:
1、每一个配置可以不用配置所有的内容,每一项内容不需要特别指定就有一个默认的行为;
2、当需要修改某项内容的默认行为,只需要修改默认配置即可,无需对每一个配置进行修改;
3、尽可能使代码能够得到重复利用,而不需要为了每一个新增加的配置项,写太多重复性的代码。(这里没有很好的体现,实际上对每一个配置,很可能还有一些诸如安全性、正确性、完整性等方面的检查代码,这些代码可能会写在GetAttribute当中。)

然后由于SalaryPage属性代码,以及其在xml当中的表现形式,导致整个配置无法达到原来设计的目的:
1、你无法保证Salary节点的内容有默认行为,也无法保证日后还会不会有其他类似的东西;
2、你无法修改默认行为,因为已经没有默认行为这一说;
3、代码也不再是重用的,进一步说就是无法保证每一个属性在诸如安全性、正确性、完整性等各个方面的标准是一致的。

今天导致我立即抓狂的是,突然发现系统在某一种情况下出错,调试后发现原来是类似Salary的地方,有某些配置不正确(实际上就是“默认配置”错了)。结果写这个东西的人跟我说,你每一个配置都打开来看一遍吧。听了我就狂晕,要这样当初设计这个配置系统干嘛?这个系统本身花了工夫去写出来就是为了避免这样的问题,现在又Fallback回去了……
至于其他的问题,我想都不敢想了,虽然没有遇到。

本来这样的问题不应该发生:
1、要么按照系统的设计,添加到<UserRole salaryQueryPage="...">当中;
2、要么xml还是按照现有的方式修改,但是代码也要遵从原有设计的意图,修改成字节点的属性也是能够有默认行为的。

实际上这样的修改很难吗?一点也不难。这样的修改很费时间吗?也许费一点时间。但绝对不会比发生错误之后,调试半天最后让我每一个配置都查一遍来的要少!可是怎么说都还是会有人不明白这么一个问题,即,修改错误的时间比开发的时间要长,修正这样的问题代码给开发人员所带来的痛苦,也远比开发一段代码要大。这就是现实,遇到这样的现实多了,你就只好举手投降。他们没有哪个意识,或者上头不给他们一种痛苦以驱动他们注意这样的问题,那么你再怎么注意,事情也还是没完没了——你创造了世界,他们来毁灭。好比随地吐痰的问题:我爸有一次随地吐了口痰,我妈就说他。他说了一句:“我不吐照样有人吐,路上照样是脏的。还不如我也一起吐,大家都吐,吐得地上都是痰,市领导实在恶心不下去了顶一个不准随地吐痰大小便法,吐一口痰扣1000块钱收监3个月,你看还有没有人吐痰?!所以我不吐痰不解决问题,我吐痰倒能够解决问题。”(我添油加醋了一番,望老爸看了不会介意。)如此说法,看来也不无道理。

要是你是一个小卒,要是你也遇到了这样的情况,那么你千万不要有代码洁癖——那绝对是没完没了地事情。赶紧发挥你的智慧,把代码写的有多烂实多烂,领导总有看不下去的一天。只有到了这一天,你的痛苦才算是有解决的希望。

其实说白了,如果你那里有这样的人存在,用NH、用Atlas、用XXX都不管用,代码照样会是一团糟。使用的高级货封装得越好,问题越是严重。假设是NH,如果Murderer有一个紧急任务,他着急要实现一个什么功能,但是不太懂NH,稍微弄了一下没有弄出来,结果必然是直接在.aspx.cs上面添加一段操作数据库的代码。这堆代码直接围绕着DataTable操作,连对象都不会给你生成,也不要期待什么防范Sql注入攻击了。到时候你想改回NH,恐怕是会比我现在还要抓狂的。

从技术的角度讲,防止类似Murderer的Destruct行为,有哪些切实可行的手段?(不讨论行政手段。)
比如说TemplateMethod模式,或者多做CodeReview?老实话,我对这两者均不抱期望,要么实际效果不大,要么成本太高却只解决表面问题,下次依旧。难道只有行政手段才能够解决问题?

再次抛砖引玉,望众人多多讨论。

posted on 2007-04-12 15:28 Sumtec 阅读(2300) 评论(12)  编辑 收藏 所属分类: Design & Architecture公司

评论

#1楼  2007-04-12 16:11 一味      
现实中这样的开发者大有人在,甚至说是普遍存在的,我觉得原因在于,你把编程当成爱好,他们当成是吃饭的家伙。事实上,我们要向他们妥协,不妥协的结果就是项目重担你一人挑起吧。有十个你也得累死。
  回复  引用  查看    

#2楼  2007-04-12 17:19 Jeffrey Zhao      
开发人员的自主性不高。所以大公司能够执行Code Review而小公司不行,技术人员之间的“觉悟”不同啊。
  回复  引用  查看    

#3楼  2007-04-12 18:11 Anders Cui      
必须建立一个简单可行的规范来约束
对于那些习惯于“破坏“的人来说
他们是不会主动去改变习惯的
  回复  引用  查看    

#4楼  2007-04-12 18:42 oldercare [未注册用户]
看不懂,有些头晕
  回复  引用    

#5楼  2007-04-12 18:43 healther [未注册用户]
# re: Destruct! 2007-04-12 18:42 oldercare
看不懂,有些头晕 回复 更多评论

  回复  引用    

#6楼  2007-04-12 20:11 双鱼座      
部分同意。我觉得,如果你想建立一个标准,你最好搞得不那么容易destruct,当然不可能是完全避免,但是要实现让他destruct规范的成本高过遵循规范的成本。习惯不是一天养成的,如果你不重视培养他们的习惯,你就不能怪别人。
再说你的例子。你不要给他机会可以直接读取配置,而是给他一个配置对象,这些配置对象已经处理好了内部的逻辑关系。例如,你这些角色的配置是分级的,级之间是可以继承的。配置项不可以任何添加或减少节点,而只能add或者remove。你的配置对象总有一个有效的配置项。
再如使用NH或者别的你认为规范的数据访问,你也有机会避免的。譬如你可以完全隐藏连接串,你甚至可以完全加密,总之令他不可能轻易获得。他还能够自己写代码围绕DataTable转么?
CodeView不是灵丹妙药,总是治表不治本。培养习惯才是正解。其实培养习惯的成本也很高,不过那可以分在一个相当长的阶段中,所以分摊下来,其实并不高。每个人的习惯都可以培养么?当然不是。有一种人是无可救药的,办法很简单。放弃他。
  回复  引用  查看    

#7楼  2007-04-12 20:53 Cat Chen      
除非你是个好的导师,能够引导他习得良好习惯,否则行政约束是必须的。有了行政约束,才能建立技术上的约束框架,规定他怎样开发出来的东西叫做合格。
  回复  引用  查看    

#8楼  2007-04-12 23:58 亚历山大同志      
基本上把一个人培养成合格的Coder之后他就会跳槽了
  回复  引用  查看    

#9楼  2007-04-13 09:37 RicCC      
设计思想没有被传递到开发人员身上
XP可以在一定程度上做一些改善
  回复  引用  查看    

#10楼  2007-04-16 19:36 111 [未注册用户]
一、简单介绍一下中国广告网的NEWSBAR
 NewsBar是由中国广告网(http://www.ads4cn.com)全国首创,并独立运行的系统,创办于2004-5-23。NewsBar自创办以来,以其良好的信誉得到网友广泛支持,几乎一直以每7秒增加一个新会员的速度飞速发展。目前已经突破1,200,000会员。

二、newsbar的收益来源
 会员在上网、聊天、玩游戏的同时,打开newsbar,收看其中的新闻和广告,也就是在帮广告主、企业做宣传,发给会员的费用即来源于此,即企业主、广告主付给newsbar站的宣传费用。


newsbar详细教程
一、注册newsbar帐号
1、登陆 http://www.ads4cn.com/newsbar/refferer.asp?yjjmissyou83并注册帐号,注意用户明一定要写自己的名字,这是newsbar以后为你支付你现金的唯一姓名凭证,一旦注册成功将不能改动,其他的以后有需要还可以修改
二、下载与使用软件newsbar
 1、申请到帐号登陆进去后找到下载newsbar软件的客户端(下载地址),有两个版本,一个是绿色免安装版,一个是完全安装版任何一个都可以。在这里推荐用完全安装版.
 2、下载newsbar后安装到自己的机器上,安装完毕后运行newsbar并登陆得到以下界面:
注意右边有个青色的小时钟,红色表示为登陆或者网络中断,白色表示有新闻点,里面的广告无须点。接下来要做的就是等新闻点。大约5分钟过后,下面为有新闻点是的界面,看,小时钟已经变白了此时用鼠标左击,然后它会提示你输入几个数字代码,确认数字代码正确后几可得到新闻点。就是如此简单,轻松吗:)
三、注意事项
1、一个用户,每天最多只能使用newsbar领取新闻点三个小时到四个小时。
2、有新闻点时请及时收取,因为如果三分钟后你不收取,系统将取消你这次领取的机会。

四、下面介绍介绍下使用newsbar快速领取新闻点的技巧
1、在newsbar主站上有快速积分活动,有可能的话都应该去做做
2、推荐好友进来一起使用newsbar,因为系统规定,会员每推荐成功一个新会员都将会得到系统额外的奖励,奖励是新会员收益的10%,这里注意了并不是说从新会员那拿10%给你,而是系统额外奖励的。

好了关于newsbar就介绍这里,如果你是soho一族,可以参考一下
五、newsbar收益与其会员分配模式
1、 会员在上网、聊天、玩游戏的同时,打开newsbar,收看其中的新闻和广告,由此得到新闻点。
2、 NewsBar的总收入和总新闻点数的关系:newsbar当前的利益分配比例是 95:5 ,即将NewsBar的总收入的95%平均分配到每一个新闻点。另外的5%作为系统收益和维护费用。
 公式:当月NewsBar的总收入 a 元,当月新闻点总数为 b 点,则每个新闻点可以兑换的现金为(0.95 × a ÷ b) 元,如果您当月一共有新闻点 c 点,那么当月您可以获得 c × (0.95 × a ÷ b )元 。
最低价格保证:newsbar承诺10000新闻点的价格最低为5元,即使整个NewsBar系统当月没有任何收益,会员也可以以10000新闻点兑换5元的比例获得奖金。实际结算价格将可能会远远超过此数据。

六、newsbar的信誉与其优势
1、信誉:新闻时报 NewsBar通过了中国信息产业部 的备案。国家信息产业部有ICP备案号:苏ICP备05000038号,信誉绝对可靠税务号:14000003200308250183。
newsbar和知名的网站都有合作!以下合作的网站 :
DELL电脑易趣ebay瑞星反病毒资讯网麦考林麦网
当当网上商城卓越网D1便利网莎啦啦鲜花礼品网
中国鲜花礼品网八佰拜时尚礼品网 游易航空旅行网
2、优势:拥有150万会员,并数秒即增加一个新会员的NewsBar,与其他几千访客的一个小网站,广告商会愿意投入更愿意到newsbar投资!



登陆 http://www.ads4cn.com/newsbar/refferer.asp?yjjmissyou83并注册帐号

  回复  引用    

#11楼  2007-05-03 19:10 周鹏      
你不要给他机会可以直接读取配置,而是给他一个配置对象

这句话严重同意。当然,真要做到是很难的,出现lz所说的这种情况,在哪个项目组中都大量存在,我要是碰到这种事,除了要求重写之外,没有好的解决办法
  回复  引用  查看    

#12楼  2007-05-03 20:13 周鹏      
对于这种程序员,要么培养他。要么开掉算了
  回复  引用  查看    


标题  
姓名  
主页
Email (博主才能看到) 
验证码 *  看不清,换一张 [登录][注册]
内容(请不要发表任何与政治相关的内容)  
  登录  使用高级评论  新用户注册  返回页首  恢复上次提交      
"五向定位"职业成长路线公开课(上海、南京、大连)
Google站内搜索


相关链接: