LabVIEW 读取 DLL 函数中的字符串的一个小经验

我们以前在编写 LabVIEW 调用 C DLL 的程序的时候,使用以下策略读取 DLL 函数中的字符串:
1. 如果能够确保在符串小于 256,比如参数名的字符串等等,就直接在 LabVIEW 中开辟一块大小为 256 的内存。
2. 如果不能保证字符串大小,就要为一个读取字符串的 VI 提供两个 DLL 接口函数,先调用一个函数得到字符串的大小,然后在 VI 中开辟内存,之后调用第二个函数得到字符串。
我在使用中,发现第一条策略不保险,应该全部使用第二条策略。
广告

为 VC 安装 STLPort

  1. www.stlport.com 下载。
  2. 解压缩。
  3. 在你的 VC bin 路径下(VC 6 默认是 C:\Program Files\Microsoft Visual Studio\VC98\Bin),运行VCVARS32.BAT。
  4. 到你的 STL Port 解压缩路径下的 src 文件夹,一次运行如下命令:
    copy vc6.mak makefile    (如果是安装在 VC 6 下)
    nmake clean all
    nmake install
  5. 成功 :)

MSI Installer 中的升级

    这是我遇到的一个 MSI Installer 的问题。
    当目标机器已经装有一个旧版本的软件,现在我们又产生了一个新的安装包,并且在新安装包中制定了升级策略。在目标机器上安装新版本软件后,发现一些文件没有被安装上。使用 MSI Installer 的修复功能,缺失的文件才被装上。
    这是 MSI Installer 的 Component 的升级策略所决定的。MSI Intaller 规范认为,所有的 Component 在不同的版本中只应有文件的更新,而不应有文件数量的增加或减少,或文件名变化。并且,MSI Installer 为了提高效率,在安装时,是先安装新文件,再删除旧版本。由于我们平时在制作 Installer 时,为了方便,没有完全保证 Component 在不同版本下保持一致。这就造成了升级策略的混乱。在安装包运行到移除旧版本这一步时,本来不应当被删掉的 Component 也被删掉了。
 
    一个简单的解决办法是,让 MSI Installer 先卸载旧版本,再安装新文件。具体办法是把 RemoveExistingProducts Action 向前移到 InstallValidate action 和 InstallInitialize action 之间。Platform SDK上有详细说明。 这样,在升级时,会慢一些。但不至于造成混乱。

用WiX编写MSI安装包

 

WiX(Windows Installer XML)是Rob Mensching(Windows组的一个SDE)写的一个用来编写MSI安装包的工具集,已经被微软内部的很多产品组采用,例如Office组,以及我所在的MSN组,等等。

下面是WiX的一个简单例子(相当于高级的Hello World!的级别),在这个例子中编写了一个SimpleCopy.msi。安装SimpleCopy.msi将能够:

  • 创建C:\Program Files\SimpleCopy目录并拷贝一系列文件;
  • 创建HKEY_LOCAL_MACHINE\SOFTWARE\MPG Lab注册表键,该键下的DestPath变量存储了一个文件路径,DestPath可以在msiexec命令行中用DESTPATH来指定;
  • 创建名为SimplyCopy的Scheduled Task,该任务每小时运行一次,执行C:\Program Files\SimpleCopy\SimpleCopy.exe,将该目录下data\source.xml拷贝到DestPath中指定的目录;
  • Uninstall时,安装时拷贝的文件、创建的注册表键和Scheduled Task都将被删除。

下面就是用WiX编写SimpleCopy.msi的步骤:

1. 从http://sourceforge.net/projects/wix下载wix的2.0.3220.0版本并解压到硬盘,将candle.exe所在的路径添加到Path环境变量中;
2. 用C#编写SimpleCopy.cs并用csc.exe在同一目录下编译成SimpleCopy.exe:

using System; using System.IO; using System.Reflection; using Microsoft.Win32; namespace SimpleCopy ...{ internal class Application ...{ [STAThread] private static void Main(string[] args) ...{ string sourcexml = GetExecutableLocation() + @"\data\source.xml"; if (File.Exists(sourcexml))...{ DateTime now = DateTime.Now; File.Copy(sourcexml, Application.QueryDestPath() + @"\source_" + now.ToString("yyMMdd_HH.mm.ss") + ".xml", true); } else...{ StreamWriter writer = new StreamWriter(QueryDestPath() + @"\error.log", false); writer.WriteLine(DateTime.Now.ToString()); writer.WriteLine("Cannot find source file: " + sourcexml); writer.Close(); } } private static string QueryDestPath() ...{ RegistryKey regkey = Registry.LocalMachine.OpenSubKey(@"SOFTWARE\MPG Lab"); if (regkey != null)...{ object obj = regkey.GetValue("DestPath"); if (obj != null)...{ return obj.ToString(); } } if (false == Directory.Exists(GetExecutableLocation() + @"\regkey_not_found"))...{ Directory.CreateDirectory(GetExecutableLocation() + @"\regkey_not_found"); } return (GetExecutableLocation() + @"\regkey_not_found"); } private static string GetExecutableLocation() ...{ return Directory.GetParent(Assembly.GetEntryAssembly().Location).ToString(); } } }

3. 在SimpleCopy.cs同一目录下创建"data"子目录,在data\下创建一个任意内容的source.xml;
4. 在SimpleCopy.cs同一目录下编写SimpleCopy.wxs,其Schema文件wix.xsd可以在wix下载解压后的doc目录中找到。SimpleCopy.wxs内容如下:

<?xml version='1.0'?> <Wix xmlns='http://schemas.microsoft.com/wix/2003/01/wi'> <Product Id='c859431f-086d-4840-b2d7-a84b3bce50f2' Name='SimpleCopy' Language='1033' Version='1.0.0.0' Manufacturer='MPG China'> <Package Id='2738eb03-978b-4712-8e21-7e1868c74c2f' InstallerVersion='200' Compressed='yes' /> <Property Id='DESTPATH' Value ='C:\'/> <Media Id='1' Cabinet='product.cab' EmbedCab='yes' /> <Directory Id='TARGETDIR' Name='SourceDir'> <Directory Id='ProgramFilesFolder' Name='PFiles'> <Directory Id='AppDirectory' Name='SimpleCp' LongName='SimpleCopy'> <Component Id='ExecutableFile' DiskId='1' Guid='379ccaeb-a8c9-448e-a4b3-fa9884676492'> <File Id='SimpleCopy_exe' Name='SimpleCp.exe' LongName='SimpleCopy.exe' src='SimpleCopy.exe' /> </Component> <Directory Id='DataFolder' Name='data'> <Component Id='SrcXml' DiskId='1' Guid='746496f1-d2b1-4334-9b6f-00f71938c459'> <File Id='Source_xml' Name='source.xml' src='data\source.xml' /> <Registry Id='4e10403a-1976-447f-b38c-59839cb7c5cb' Root='HKLM' Type='string' Key='SOFTWARE\MPG Lab' Name='DestPath' Value ='[DESTPATH]'/> </Component> </Directory> </Directory> </Directory> </Directory> <Feature Id='AllFiles' Title='Simple Copy All Files' Level='1'> <ComponentRef Id='ExecutableFile' /> <ComponentRef Id='SrcXml' /> </Feature> <InstallExecuteSequence> <Custom Action='CreateScheduleTask' After='InstallFinalize'>NOT Installed</Custom> <Custom Action='DeleteScheduleTask' After='InstallFinalize'>Installed</Custom> </InstallExecuteSequence> <Property Id='SCHTASKS'>SCHTASKS.exe</Property> <CustomAction Id='CreateScheduleTask' Property='SCHTASKS' ExeCommand='/Create /RU "" /SC HOURLY /TN SimplyCopy /TR "%ProgramFiles%\SimpleCopy\SimpleCopy.exe"'/> <CustomAction Id='DeleteScheduleTask' Property='SCHTASKS' ExeCommand='/Delete /TN SimplyCopy /F'/> </Product> </Wix>

5. 打开命令行,进入SimpleCopy.cs所在的目录,先后运行candle SimpleCopy.wxs以及light SimpleCopy.wixobj,然后就得到SimpleCopy.msi了:

6. 在命令行运行“msiexec /i SimpleCopy.msi /quiet /log log.txt DESTPATH=d:\”就可以安装了。

相比较其他MSI编写工具(例如Visual Studio 2003/2005,以及InstallShield等),WiX的优点是:

  1. 便于版本控制(wxs是纯文本的);
  2. 便于自动化(编辑工具candle.exe和light.exe都是命令行的)。

C# 中的接口与抽象类

 

一.接口的定义

定义:定义一个协定。实现接口的类或结构必须遵守其协定。

简单的说就是接口或者类之间交互时遵守的一个显示定义。最初接触“类与类之间通过接口交互”这个概念时,误以为接口就是类公开的方法,类之间通过类的方法进行交互。其实接口是独立于类的一个定义。接口定义类之间交互的标准。

那么类与类之间直接交互就好了,为什么还要使用接口呢?

这主要是因为:接口是类之间交互内容的一个抽象,把类之间需要交互的内容抽象出来定义成接口,可以更好的控制类之间的逻辑交互。可见接口内容的抽象好坏关系到整个程序的逻辑质量;另外可以在任何时候通过开发附加接口和实现来添加新的功能;

关于接口一个很重要的概念:接口只包含成员定义,不包含成员的实现,成员的实现需要在继承的类或者结构中实现。

接口的成员包括:方法,特性,索引器,事件。

注意:接口不包含字段。

实现接口的类必须严格按其定义来实现接口的每个方面

      接口本身一旦被发布就不能再更改,对已发布的接口进行更改会破坏现有的代码。

一个典型的接口示例:         

using System;

using System.Colletion;

public delegate voic Chang(object  sender,object event)//定义一个委托

public interface Ibroker  //定义一个股票经济人接口

{

  string GetRating (string stock);//一个获得金额的方法(此处没有实现)

  decimal pricePerTrade    //定义一个设置每股价格的特性

  {

get;                //没有实现的

set;

}

decimal this(string StockName)    //定义索引器

{

  get;

  set;

}

event Change pricechange;   //定义接口的事件

}

 

二.接口与抽象类

   抽象类和接口在定义上和功能上有很多相似的地方,具体在程序中使用抽象类还是接口需要比较抽象类和接口的具体差别。

抽象类:一种不能实例化而必须从中继承的类,抽象类可以提供实现,也可以不提供实现

        子类只能从一个抽象类继承

       抽象类应主要用于关系密切的对象

       如果要设计大的功能单元,则使用抽象类。

       如果预计要创建组件的多个版本,则创建抽象类

 

接口:是完全抽象的成员集合,不提供认识实现。

类或者结构可以继承几个接口。

接口最适合为不相关的类提供通用功能

如果要设计小而简练的功能块,则使用接口

接口一旦创建就不能更改。如果需要接口的新版本,必须创建一个全新的接口

三.接口的的实现

   接口的实现分为:隐式实现和显式实现。如果类或者结构要实现的是单个接口,可以使用隐式实现,如果类或者结构继承了多个接口那么接口中相同名称成员就要显示实现。显示实现是通过使用接口的完全限定名来实现接口成员的。

针对上面的例子 我们可以这样实现接口:

public class testInterface: Ibroker  //定义一个继承ibroker接口的类

{

  hashtable hash=new hashtable();

  decimal pricepertrade;

  public testInterface(decimal price)   // 构造函数

  {

    pricepertrade=price ;             //初始化字符串

}

public string  Getrating (string stock)     //隐式实现接口的方法

{

   return “buy”;

}

public decimal Ibroker.pricepertrade //  显式实现接口的特性

{

  get

{

  return pricepertrade;

}

set

{

  pricepertrade=value;

pricechange(“Finacebroker”,value);

}

 

public decimal this(string stockName)

{

  get

{

  return (decimal)Hash[stockName];

}

set

 {

   hash.add(stockname,value);

}

}

}

public event changer pricechange;//接口中的所有成员都要实现

}

四.接口中的多态

 多个类继承了相同的接口就实现了接口的多态性,接口的多态性的访问和类的多态性访问一样。下面的例子说明怎么实现接口的多态性访问:

public class InterfaceTester

{

  public stratic int Main (string[] args)

  {

string recommendation;

Arraylist Brokers=new Arraylist;//定义一个列表

Brokers.add(new  firstBroker(7.21m));//添加第一个继承接口的类

Brokers.add(new  secondBroker(12.3m));// 添加第二个继承接口的类

InterfacetTester new Iftst=new InterfacetTester

Foreach (Ibroker broker in Brokers)

{

   broker.pricechange+=new change(iftst.pricepertradechange);

   broker[“adc”]=12.33m;

   broker[“rty”]=11.23ml

   broker.pricepertrade=12.55m;

}

}

}

《No Excuse!》

  二次世界大战以后,在世界500强企业里,有大约1000名董事长,2000名副董事长,5000多名总经理毕业自同一所学校。没有任何其他一所学校可以与之相比。这所学校就是西点军校。
  最近读了 Ferrar Cape 的 No Excuse! 这是作者对西点培育人才精髓的总结。与大多数的商学院或是MBA课程不同,西点不是教导学员如何做一个优秀的领导(将军),而是教导学员如何做一个优秀的员工(士兵)。但是结果却是西点军校培育了3位美国总统在内的大量领导人物,远胜于其他的商学院。
 
  一个优秀的员工或士兵应当是这样的:老板交给他一项任务,他会自己想办法解决所有的困难,完成任务。而不是推托,或质疑任务的可行性,必要性等。我知道有另外一本书:《致加西亚的信》也提出了类似理论。但我还没读过,过一段时间会祥读一下。《致加西亚的信》一书中的安德鲁·罗文就是一个这样的士兵。当时正值美西战争,美国总统麦金让罗文中尉送一封信给不知正在哪里打游击的加西亚将军。罗文中尉二话没说,自己克服了所有阻力,最后古巴丛林里找到了加西亚将军,并把信交给了他。
  Ferrar Cape 认为,决定一个员工是否优秀的是他的责任感。一个人的责任感有多强,他就会最终做到什么位置上。《No Excuse!》通篇就是一本教人树立责任感的书。
 
  《No Excuse!》的理论也是有局限的。它的前提条件是要求一个人所处的环境是比较公平的,一个人的提升是因为他的工作表现,而不是因为关系网或者拍马溜须等等。比如,你正在中国官场混,就没必要看这本书,还是《厚黑学》比较有用一点。对于在外资公司的员工,或是准备出国发展的人,《No Excuse!》是绝对值得一读的!

Should Private Cars be Encouraged in China

    If you ask me, the answer is YES.  I am always eager to own a personal car.  Don’t you have the same dream?
    Many people are against owning private cars because of some obvious reasons, such as air pollution, noise, traffic jams, and resource waste.  But I don’t think that any of the above issues belong to the automobile uniquely.  It is the industrialization that has brought us all of the problems.  Why don’t we just stay in the agricultural society to avoid those troubles?
    We should not always focus on the disadvantages of the cars but overlook their contributions and our great capabilities of overcoming the problems.  Some cars have already adopted fuel batteries instead of gas engines.  Cars will hardly generate any pollution when hydrogen replaces gasoline as the fuel.  With cars, we run into traffic jam sometimes, but without cars, we will have to be congested at downtown all day long.  We all dream of the rusticity, but without the car, life in the suburb is just a tragedy.  Cars provide us much more convenience than troubles.
    The automobile industry will contribute to our national economy enormously, just like what it has done for the American economy.  As one of the mainstay industries, the auto industry will accelerate the progress of mining, manufacturing, capital construction, and other related domain.  It will also provide tremendous employment opportunities.  Domestic demand is playing a more important role in Chinese economy more than ever before.  Private cars are the best stimulus of the demand expansion.
    A private car is a symbol of freedom of individuals, and also an index of development level of a nation.  There is no doubt that our government must encourage the development of private cars.
 
相关连接:
 
 

The “Only Child” Generation

    The majority of Chinese families now have only one child since the one-child policy has been in place for nearly 20 years.  By the year 2001, there was already 240 million “only children”, which is about the population of the United States.  In the next couple decades, the “only children” generation will become the elite of our society.  No one knows how much he or she will change the world.
    As the only child in the family, he or she received more elaborately attendance, sometimes, even indulgence.  Parents always try hard to fulfill each of his or her requests.  Those children, who are called as “little emperor”, are in the danger of being spoilt, over pampered and self-centered.
    As the center of the families, the kids, without any siblings, still feel lonely, which is the origin of many kinds of psychological illness.  Neither the parents nor the classmates can take place of the role of brothers and sisters.
Seems the “only children” are still not ready to take their responsibilities.  Some elder “only children” has already graduated from universities.  But they still can’t be independent from their parents.  The “only children” usually require longer period to season the change in their career, because they were brought up in a more sheltered and more dependent environment.
    When their parents have been retired, a couple of “only children” will have four parents and even more grandparents to look after.  It will surely be a disaster if we don’t well prepared to face it.
 

相关文章:

    英语作文

 

编辑

生物进化思想与程序设计思想的比较

阮奇桢
我的职业是软件工程师,编程序的。研究生专业是生物医学。我对计算机和生物都挺感兴趣的,所以平时这两方面的书都喜欢看。这两门学科虽然相差较远,但有些思想还是可以相互借鉴的。这篇文章就是介绍一下进化论的各种理论对我的程序设计思想产生的影响,以及在学习了编程思想后对进化论的反思。
一、基因突变、物竞天择思想在编程算法中的应用
有一门学科叫遗传算法,里面详细阐明了把各种遗传、进化思想引入到计算机科学的理论,比我研究的透彻多了。但是,在这里我还是叙述一下我在接触这门学科之前的一些朴素的想法。
最初遇到这个问题是这样的:我一个朋友刚学了黑白棋(Othello),找我来下。我不会玩,虽然他的水平也很臭,可我还是下不过他。后来我就想,我下棋水平不行,编程水平还可以,能不能编个程序赢了他呢?问题是我又不太懂黑白棋,如何使编出的程序如何比我的水平还好呢?
首先,黑白棋比较简单,算法容易实现。计算机算得比我快,按照我同样的思路下棋,也应该比我下得好一点。
其次,我就在考虑如何能让计算机通过学习,自己不断的提高技术。我当时就是受了基因突变、物竞天择这个思想的启发:让不同的程序之间互相下棋比试,输了的被淘汰,赢了的就有机会繁殖后代,然后再在后代之间比较。理论上,程序的棋力应当一代比一代强。
具体实现方法就是先提取下棋时可能对输赢产生影响的参数,比如落子的位置,每个子周围的空格数,己方可落子的位置数、低方可落子的位置数等等,类似的能列出几十条。我不确定这些因素是否都会对结果产生影响,因为自己的下棋水平就很差。但是这不要紧,这些参数统统列出来好了,多多益善。这些参数就相当于生物体的基因。每个下棋程序的框架都是一样的,只是这些参数的值不同。
组织几十个下棋程序进行循环赛。名次排在后一半的都淘汰。成绩最好的那些程序有机会把全部基因保留下来,还可以和其他程序交换一定的基因,还可能有一定的随机突变。最后又生成了几十个程序,这是第二代。换句话说,成绩好的程序,后代多一些;成绩一般的,后代少一些;成绩差的美后代。然后再它们的后代之间再进行比赛,选拔,又生成下一代。这样循环反复。程序的水平就越来越高了。
在实践中,我就是用这个程序经过一定时间的子学习,赢了我的朋友,很有成就感
不过用这重思想样写出来的程序是有一些明显缺陷的,主要就是效率太低了。程序的下棋水平进步的非常慢。这点想一想生物界也可以理解。生物进化了几十亿年,才到现在的水平。就算我这个程序比生物进化的效率高,取得个明显进步也得个上百年吧。
再有,我程序每一代的样本也太少,只有几十个。生物界里,每种生物一代一般也得有几百万,几千万的个体。而我的程序等于全都是近亲结婚,弄不好还会水平一代比一代差。这两个问题的解决受限于计算机的运算和存储能力。
遗传算法上介绍的算法比我的解决方案成熟多了,但是我刚刚提到的的缺陷也同样存在于遗传算法中。有兴趣的可以看看这方面的书。
二、对进化论的反思
我的采用基因突变、物竞天择思想编出来的下黑白棋的程序,如果就让他这样运行下去,过个几万年有没有可能进化成下五子棋或是其他什么棋的程序呢?
达尔文的 进化论,在很多国家,只是算作假说。而在我国,由于政治的原因,是当它做真理来传授的。
达尔文在他的《物种起源》里提出了两大假说,其一是“同源说”,认为地球上的所有物种都起源于同一个细胞。同源说基本上被大家接受了,在学术界上反对的声音相对较小。而另一假说,是用来解释现在的物种多样性的,就是基因突变、物竞天择的进化论。但是它从一开始就受到了强烈的质疑。
达尔文的时代还没人能证明基因的存在,50年前DNA的发现给了进化论以强大的支持。但是把物种的多样性归结为基因突变、物竞天择我觉得还是有很多不妥之处。
进化论有三大证据: 比较解剖学、古生物学(化石)和胚胎发育的重演律。
比较解剖学发现人和猴子的骨胳相类似,所以证明人和猴子是共同祖先演化来的。有人认为这是循环论证,因为如果有人问为什么人和猴子的骨胳为什么相似,原因是人和猴子有共同祖先。我到不这么认为,原因是人和猴子的骨胳相似是现象,而不是结论。现象不需要证明,不论进化论对这一现象的解释合理不合理,都不影响这个现象作为事实存在。这一点可以用来证明同源说,但解释不了生物演变的过程。同源说在发现基因后得到了进一步证明,不用生物间,即便是人类和单细胞细菌间也存在高度同源的基因。但这一点对我们编程序影响不大。
按照基因突变的理论,生物进化的进程应该是一个均匀连续的过程。然而,在出土的化石中,基本都是物种分明的,很难找到介于不同物种的中间过渡类型。能作为过渡类型的化石只有始祖鸟等极少的几个。相对于其他的成千上万的物种的化石显得太微乎其微了。
大多数化石展示的都是突然出现的某种有机体,这些有机体一旦出现,基本上就不再变了,直至消亡,哪怕这个过程要历经几亿年。例如:在30亿年前到5亿年前之间的化石全部都是单细胞生物的。然而,在5亿年前,似乎一夜之间,各式各样的多细胞生物就出现在了海洋里。所有可以找到的化石都属于这些物种,根本没有介于他们之间的过渡类型。动物界有十个门,脊索动物门是哪来的?是从原生动物门进化来的,还是从棘皮动物门进化来的?像类似这些问题,在化石里一点线索都找不到。因此,但从化石来看,倒是更能证明基因突变的理论的不完善。
再想一下本段开头的问题,我黑白棋的程序,如果就让他这样不停的基因变化下去,他会进化成下五子棋或是其他什么棋的程序吗?我认为不会。
至于胚胎发育的重演律则更有问题。既然基因已经突变,就不应该再保留原有的信息,失去了原有信息就不应该有重演。除非生物进化不是基因突变引起的。
所以这三大证据,均不能证明基因突变的理论。
三、程序是如何“进化”的
我的黑白棋自己是不能进化成五子棋的,但在我的帮助下却是可以的。
我程序使用C++编写的。熟悉C++的人即使是个小程序也会把面向对象、泛型编程这样的思想用上,我也是这样。
比如我又打算编一个下五子棋的程序,该怎么写呢?两种棋有很多相似的地方,比如棋盘的类型,棋子等等。全部从头再创建一个五子棋程序显然是不合适的。
最土的利用源代码的方法是把原来的黑白棋程序拷贝一份,然后在其基础上改写一下。这样做的缺点是,我的两份程序中有重复的代码,这样不利维护。比如我改进了黑白棋中一部分代码的性能,我还得再想办法把他移植到五子棋上来。相同部分的代码应该只有一份,就比较利于维护了。
有了面向对象的编程方法,这个问题就好解决了。我可以把黑白棋中创建的类作为基类,派生出五子棋的类。五子棋中不同于黑白棋的属性和方法,可以用新的属性和方法把它覆盖(override)掉。这样做,被覆盖的属性和方法他们的代码还在,但在执行时已不起作用了。但有些父类的代码,还会继续起作用。比如,子类的构造函数通常会先调用父类的构造函数,然后再执行自己的代码。这样一来,父类的某些特征就会在子类实例中体现出来。尤其是在构造子类实例的过程中。
这像不像胚胎的重演过程?
四、生物的进化的新假说
参考软件自动进化的规律,我提出一个假说:基因突变只会导致同一物种的小变化范围内的改良。而能够导致物种变化的主要是基因上类似“继承”的操作。
按照现在的研究成果,高等生物体的染色体都存在有大量的“无用”基因片断。这些基因片断在生物进化的历史上或许并不是无用的,他们曾经是对这种生物发育起到作用的。但是,随着新的基因片断被加入到该生物体内,某些新基因片断可能与旧有基因片断存在着类似的功能,但优先级更高,抑制了原来基因片断的活性。之后,生物体所体现出来的行为就都是由新的基因片断决定的,原有的片段就成了无用片断了。
至于新片断是哪来的,我想首先可能来自于有性繁殖。有性繁殖除了把父母的两条染色体合成一对,有时也许还会带入全新的基因片断。其次,低等生物,比如细菌,个体间会有基因交换行为。新片断也可能来自于病毒的传播,或者通过饮食等途径带进来了。
五、未来软件的发展趋势
生物进化了30亿年,才达到现在的程度。计算机软件出现了不过50年。这两者目前似乎没有太多的可比性,但是我想在人类智慧的帮助下,软件的进化速度会大大高于生物的进化速度。出现拥有智慧的,可以自我完善软件也许只需几百年,是生物进化速度的 10,000,000 倍。我们不妨大胆预测一下未来软件的发展趋势。软件未来的发展也一定会与生物进化有某些类似的地方。
最近我开始着手更新一部分程序代码。这部分代码存在于公司一个非常大型的应用软件中,我需要修改的这段代码已经有很多年的历史了。其风格,按现在的观点来看,是非常差的。比如说变量名都是用单个字符表示的、存在大量硬编码等等。如果是年轻几岁的我,看到这段代码会认为根本没有维护它的必要,就应该把他们彻底抛弃,重写一遍。事实上,公司里确实有人曾经试图这样做过:刚看到很原始的代码,对他嗤之以鼻,又对自己的能力充满自信,于是开始对部分代码重写。但最终,这些尝试都以失败告终。
在一个有些历史大型软件中,遗留着着几十年前的代码是很正常的。这些代码不是不可以被改写,但是如果综合考虑代价和收益,可能改写他们是非常不合算的。一个大型的软件,经过几十年,被成百上千的人改动过,它当中相当一部分代码都会被软件中其它的地方引用到。到最后,没人能够说得清楚这段代码全部用途了。如果只做了少部分验证,就贸然把这段代码重写,新写的代码在功能上很难保持与原代码完全一致。将来会慢慢发现,新代码引入的bug和潜在危险远比它带来的好处大。
现在生物学上,研究基因片段功能的方法主要是,先把一段基因敲掉,然后看看他对生物体带来了什么影响。然而大多数基因被敲掉以后,却看不出生物体受到了明显的影响,这就是那些“无用”基因片断。这一是因为上面提到的基因有备份,备用基因会及时发挥作用,弥补缺失的基因的功能。还有就是很多基因的功能是和其他很多基因共同作用才能显现出来的,或者是在某些特殊情况下才会被显现出来的。这些基因的功能不是那么容易被观察到的,他们缺失了,或者被添加到一个本来不具备这种基因的生物体上,它们的潜在的影响或许要过很多年才能被发现。现在大家对转基因作物的戒心,这也是原因之一。(对转基因食物更大的担心可能是在于,被植入的基因片段不够稳定,更容易整合到人体基因中去,导致人类的基因被转化。)
那么针对这样一段老的代码,需要修改其bug,或是增强某些功能,最好的办法不是重写它,而是把它原封不动的留着,在它的上层再写一层外壳。在这层包装层内对源代码的功能加以修正。以后再用到这段代码的功能时,调用包装层提供的函数。
比如说源代码是个除法运算,但是没考虑除零的特殊情况,我们不是去改动源代码来判断参数是否为零,而是为它包一层新的函数。在新函数中先检查除数是否为零,如果是,进行错误处理;否则调用原代码进行除法运算。新的程序再用到除法功能就试用新写的函数。这样做的好处是:原本那个除法可能被用在了系统中的很多地方,或许某个地方就是要利用它的除零错误。你不能百分之百确定没有这种情况的出现,就贸然改变这个函数的行为。结果在系统的其它部位又引起了新的bug。这个新的bug更危险,因为你还没有意识到它的存在。
如果要改进的是个类,那么就在原来类的基础上派生出一个新的类。在新类里覆盖或添加一些功能。原有的类也是保持不变。
这种做法是有明显缺点的,就是空间效率太差。用这种方法维护的程序,体积会飞速膨胀。但是随着科技的发展,计算机存储设备开销,相对于软件维护来说会越来越便宜。迟早有一天,软件的大小将不再是一个需要考虑的问题。
程序越大,bug越多,相信永远都不会出现所谓的“完美程序”。随着软件规模原来越大,花再多的时间测试,也不能保障一个应用系统没有出现故障的可能。对于某些关键部位,一旦就问题出现,损失可能是不可接受的。那么在这些部位,最好的解决办法就是备份。硬件系统设计中,备份是很普遍的。软件系统承担起越来越多的工作后,也必然要采取这个方案。对同一功能,按不同的思路写两套实现代码。系统平时只用其中一份,一旦出现异常,系统就把另一份调出来使用。
生物的基因都是成对的,这不仅是为了繁衍后代,更是为了备份。如果某一条基因出现的缺损,另一条上的对应部位可以立即接替相应的功能,保证整个生物体的正常运作。
相关文章:

.NET Framework 的容器

  自从我发现了STL,再编写C++程序,就离不开它了。STL提供的容器和算法极大的方便了C++编程。
  最近在对比研究C#中的泛型、标准容器和算法,看看它是如何实现类似STL的功能的。先总结一下C#中的标
准容器。我使用的是 Visual C# 2005。
 
  C# 中主要有两类容器:一个是 System.Array 类(参阅:http://msdn.microsoft.com/library/default.asp?url=/library/en-us/cpref/html/frlrfsystemarrayclasstopic.asp),类似 STL 中的 Vector;另一类是集合。集合还可以细分
成功能不同的几个容器。
  C# 1.0 的集合类的容器全部在 System.Collections 名字空间下。(参阅:http://msdn2.microsoft.com/en-us/library/k166wx47(en-us,VS.80).aspx)其中实现好的容器有:ArrayList
,BitArray,Hashtable,Queue,SortedList,Stack 。名字空间中的其它类,比如 Comparer 等,是用来帮助实现容器和接口的,就不把他们算作容器了。
  C# 2.0 由于增添了对泛型编程的支持,它又新增了一个名字空间 System.Collections.Generic,存放所有支持泛型的各种集合类的容器。(参阅:http://msdn2.microsoft.com/en-us/library/system.collections.generic)支持泛型的集合类容器有:Dictionary,LinkedList,List,Queue
,SortedDictionary,SortedList,Stack。
  与之对比对比,STL中实现的容器有:Vector,Deque,List,Set/Multiset,Map/Multimap,Stack,Queue,Bitset。
 
  下面主要介绍一下,C# 支持范型的容器。
  Array 顾名思义,提供了数组容器和操作,如查找、排序等。类似于STL中的 Vector。其声明如下:
  public abstract class Array : ICloneable, IList, ICollection, IEnumerable
  Array 与STL中的 Vector 和 C# 中的其它容器不同之处,它不需要特别的把变量用 Array 类来声明,直接在元素类型后加中括号就可以把变量指定为是 Array 容器。例如声明一个元素数据类型为int的数组容器用一下语句:int[] myIntArray = new int[5] { 1, 2, 3, 4, 5 };  语句中的 myIntArray 即成为一个数组容器。
  Dictionary 与 STL中的 Map/Multimap 相类似。Ditctionary 是两个类型参数(健和值)的集合。
  List, SortedList,与 STL中的 List 类似,提供链表容器和操作。
  Queue与 STL中的 Queue 相类似。是元素先进先出的集合。
  Stack与 STL中的 Stack 相类似。是元素先进后出的集合。
 
 

英语学习

英语作文

为了交作业和参加公司的 English Corner 我写过一些英语作文。本来都存放在硬盘上。现在是网络时代了吗,所以决定拿出来给大家共享。

英语常用语、俚语

博客版《我和LabVIEW》目录

发行版的《我和LabVIEW》现在开源共享了,地址: https://lv.qizhen.xyz/

以下是在《我和LabVIEW》一书出版前发布的LabVIEW博客文章。该书出版后的博客文章没有包含在这个列表中,点击这里可以查看新的文章:《我和LabVIEW》补充内容和注释

第〇章:序

第一章: LabVIEW 的编程环境

第二章:简单程序结构

第三章:控件、常量和运算

第四章:常用的程序结构

第五章:调试

第六章:深入理解 LabVIEW

第七章:编写优美的代码

第八章:编写高效率的代码

第九章:VI 服务

第十章:调用动态链接库

第十一章:面向对象编程(LVOOP)

第十二章:XControl

第十三章:项目管理


其它

返回《我和LabVIEW》主页

我一直拖着没做的两件事

  昨天在我的硬盘里乱翻,发现了以前从弟弟那里考来的一套有声教材《激发个人潜能》(安东尼罗宾)。于是,把第一课放在mp3里带回家听了听。那个作者真是能吹,说听完的这套课程,包我从此走向成功,说不定一不小心就成百万富翁了。
  我可不那么幼稚,成功是没这么简单的。但是成功是是需要学习的 :) 我还真没读过这类的书或上过这一类的课。而且在这方面挺欠缺的,学一学应该对我有好处。所以我决定花一个月的时间把这套课程听完。
  昨天第一课, 安老师留了道课后作业,要列出两件我一直拖着没做的事。把它记下来,然后马上去做。我这人最喜欢拖拖拉拉,这类事情要我写处两百件也不难。不过我这种拖拉的习惯的确不怎么好。这回咬咬牙,先干两件事吧:
  1. 写毕业论文。(拖了一年了,也不知道老师还会不会让我毕业了)
  2. 拔掉智齿。(拖了一年半了