2006/12/27

Err, Boolean, MemPtr

把函数的返回值设计成Boolean或者MemPtr在使用的时候是非常方便的。而且也容易理解,返回true就是成功或真, false就是失败或假。返回指针的时候,如果返回空指针就是失败了,如果是实指针就是需要的地址。

但是这两种情况就不能处理错误,除非使用C++的异常处理机制。如果把返回值设计成Err,那么错误终归是可以处理的,但是这样使用的时候不方便,而且需要处理多少错误也是个问题。

通常,私有函数可以偷偷懒,因为你很清楚这些函数在什么地方会被调用,可以约定参数都是有效的(看看参数的来源,不要有从公有函数传递过来的外部参数,否则就不能做这样的假定),这样可以用Boolean或者MemPtr这样易用的形式;但是对于公有函数,在写这个类的时候没法预料将来会怎样被调用,所以假定所有可能的参数比较好,考虑所有的错误发生情况并返回正确的错误信息。

如果用了Boolean或者MemPtr这样的形式,要看看函数内部资源失败的时候会有什么后果(比如Malloc),是否会导致数据不一致,包括内存对象和存储对象。如果会,那还是不要偷懒,否则因为小几率事件导致数据损坏的时候就追悔莫及了。

2006/12/26

数据完整性

在数据库中,有一个功能叫做Transaction,它的意思是,如果要做一系列的更新、创建、或者删除操作的话,应该有一个显示Commit;如果Commit成功,则所有的改动都生效,如果Commit失败,则没有任何改动生效----而不是部分生效。

在涉及到数据存储的时候,通常也会很好的考虑这个问题,简单的办法就是做一个缓冲出来,全部写完之后一次性写入文件;这也要求尽量把有相关性的数据写在一个地方,否则很难保证不在多个文件写入的时候发生错误,导致数据不一致。

在对象中同样要考虑这个问题。虽然我们可以假定在函数返回错误的时候,传递的参数变量会失效(如果对象较大又不希望被改变的话,传递对象的Copy的引用,而不是直接传递引用),但是在返回错误的时候,如果本来有效的数据对象本身同样被摧毁,是不能接受的。所以不要在函数中直接改动成员变量,除非你明确知道不再可能有错误发生。不要做太大胆的假设,实际上除了MemMove这样屈指可数的几个函数之外,即使是内存分配也有发生错误的可能。较好的办法是做出一个成员变量的复制品,对这个复制品进行改动,如果过程中出现错误,丢弃这些复制品并返回错误;如果没有出现错误,那么用复制品对成员变量赋值,或者把指针指向复制品,把原件丢弃。

如果每个过程都遵循这样的原则设计,那么就不用为对象内部出现数据不一致担心了。

2006/12/25

拼音与五笔的统一

一直都被这样一个问题困扰着:既然以记忆预测作为输入法的基础构架,不同编码方式的输入法应该能统一在一个同样的框架下,因为语言蚊子本身是不依赖于编码的。

今天终于想明白了这个问题。

巨硬把同音字作为不同的字处理。其实可以不这样做。把拼音拆开成为子数组。然后在SeqNode上加一个modifier的标志,另外建一个数据库存储特殊的拼音序列,供匹配的时候查询,这样就可以依据字,而不是多音字,建立树库。可以实现不同编码输入法的词组、序列和频度的共享。

不过这是巨硬IV的任务了。巨硬III还是按照目前的算法继续下去,否则永远也无法完成可用版本了,改进永远是无止境的。

2006/12/19

改动

据说这叫做AGILE。:)

对于这个小项目来说也许不是什么大问题,只是重写几个函数而已;如果是大项目,这个就要吐血了。所以我最终理解了,我在软件上最欠缺的是设计能力;不知道是不是有人能够做到一次设计不再改动的,至少对我来说这够匪夷所思的。

今天做了一个改动,摒弃了之前关于sequence of sequence的设计,抛弃在Sequence node中嵌入Sequence reference的做法。这主要是考虑到两点:一个是增加用户输入的随意性,比如用户输入嫁,可以提示鸡随鸡,输入嫁鸡,可以提示随鸡,输入嫁鸡随,可以提示鸡;另一点很重要的,是提高性能,只要抽出一个树就可以得到所有Node的展开结果,不需要查询其他树,这对于symbian或者wm这种以flash作为存储介质的系统来说非常重要。

2006/12/18

低级错误

对于非职业程序员来说,经常重复低级错误就是编程的一大乐趣之一。我甚至在想,如果成立一个收录低级错误的网站,对Coder来说也许是很不错的去处。

今天就遇到了两个很低级的错误,其一是忘记初始化一个变量(把初始化写入Constructor这时就是一个好主意,当资源还不存在的时候这么干就不是一个好主意);其二是没想到bitwise operator的优先级竟然不如+-*/。

ANYWAY,一边搭脚手架一边盖房子的过程开始了。

2006/12/10

Coding的周末

这个周末写了不少代码。

上周看到同事演示了一下梅花在Dopod无键盘机器上的使用情况,设计得非常不错。不过我还是坚持硬按键的想法。硬按键和软键盘相比,后者的一个优势是可以动态更改键盘显示内容,梅花的作者在这方面颇有造诣。

巨硬III的算法是很独特的,目前我也不知道最终的结果是否如想象的好用,只能等做出来再看。我也在考虑用这个算法去解决一些输入法之外的智能问题,上周想好了一个例子,就是中国古老的围棋。

目前我越来越相信基于记忆树的预测方式是好过人工智能中广泛应用的盲搜路径的。但是关于严格序列的假设是否能击败Pattern识别方式就不得而知了。这里面还有一个Pattern形成的问题比较头疼,这涉及到人脑是如何发现和形成一个未知的概念。但总体来说,如果能克服这个问题,程序就可以象人脑一样去识别和学习了。围棋中有很多模糊的东西,这基本上就是一种概念形成的结果。在不同的阶段有不同的概念,比如布局、势和实地、形和子效、手筋、死活、先后、定势、管子等等。对形势判断的绝对的优劣是没有的,往往不同的人判断的结果不同,这是很有趣的一个方面。在人实际学习围棋的过程中,这些概念都是通过老师的教导和实际的感悟逐渐形成的模糊概念。

2006/12/09

Doxys

今年对我的编程生涯来说简直是一个工具年。从MindMap工具MindManager,到UML工具DIA和Visio,都对我的coding方式有很大改善。眼看着年底将至,末世情结再现,这个节骨眼上,遇到了Doxys。

Doxys是一类被称为Documentation Extraction Tools的工具。它的工作原理其实很简单,就是在代码中有一些注释的约定,符合约定的注释可以直接被转换成html的文档。Doxys基于另一个DET项目Doxygen,不过我没试过那个,据说注释风格有些怪异。这是我目前看到的最好的代码维护工具。UML更多是用于理解代码,尤其是关键代码的,把所有的代码,尤其是例程,都UML出来很不现实。而且没有直接对应关系,要保持两个地方的逻辑一致,这才是维护的时候最难的地方。事实上,无论是MindMap工具,还是UML图,还是Word一类的RTF文档编辑器,都存在这个问题。从这个意义上说,Doxys是最好的方式。

2006/12/01

UML的类图

在visio中这个称为静态结构图。

两年前我就买过一本UML。当时很起劲,还拉了一个朋友一起探讨code generation技术,UML的一个非主流的流派就是xUML, executable UML,换言之就是让UML可以自动生成可执行的程序。因为UML是平台无关的东西,这个想法很有吸引力,如果可行,程序员就不必探究平台差异的编程了。

UML的起源很复杂,所以学习UML就象学习计算机网络一样,林林总总的标准和意图,让这个技术变得不那么纯粹,甚至是颇为混乱。同样和网络一样,UML也是由为了解决很多工程上实际遇到的问题出现的,它更像一箱子组合工具而不是一把万能工具。

我一直被这样的问题困扰着:随着程序不断膨胀,类和函数越来越多,文件也越来越多;类之间的关系让人很头疼,无论代码还是文档都不直观。我也尝试过用powerpoint和mindmanager画了很多图,仍然不方便,所以这两天又把UML的书翻出来看了看。有点心得了。

好处:
1。UML类图可以很好的给程序结构一个总览。这是其他工具很难做到的。
2。UML有关于类之间的关系的严格定义,这比MindManager或者Powerpoint流程图那种不规范的东西好的多,规范的一个好处就是强迫你去按照严格的逻辑去思考,而不是在字面的意思上较劲。

缺点:
1。UML关于关系的定义需要花满多时间去学习。
2。UML并不是能表达所有的关系

底限:
1。不要试图把代码中的所有东西都放到UML中去,一些一望可知的东西和次要的东西不必放进去。
2。UML的目的是帮助理解代码,而不是和代码建立严格的逻辑关系或者生成代码,简单、直观、没有歧义是最重要的。

UML类图对开发进度的管理也因该有很大帮助,可以在代码和UML图之间往返工作:

1。先根据文档想清楚关键的算法和逻辑
2。在UML中画出除了基础类之外的类,尤其是那些需要在不同类之间作为参数传递的类,在开始的时候就统一一下,不要在写程序的时候不断添加这样的类。
3。把这张图画的平衡一些,把一些很小的、有强依赖关系的类合并到其他类中去,可以作为一个public成员存在。这样可以有效减少类之间的关系数量。
4。仔细考虑一下那些会很很多的类打交道的类,看看这样的类是不是功能很单一,是不是可以作为一个包中最大的容器类的一个函数存在,而不是作为一个类存在。

减少类之间的关系有助于理解和简化结构,当然,不能为了这个目的把类中大量添置操作,把不相关的操作都放到一个类中去,这也违反封装的独立性原则。要平衡类的操作数量和类的关系数量。