高内聚、低耦合、SOA 和测试驱动。

软件工程:

随着软件工程的不断膨胀,功能的扩展变得愈发困难,因为增加一点点小功能而导致的 Regression 可能会越来越多,同时,因为项目越来越大,参与的人越来越多,代码的结构化、模块化便成了高质量产品非常重要的特性之一。

高内聚和低耦合,其实是好的模块化编程必须具备的两项特点,高内聚,我的理解模块独立完成特定,不重复实现其他模块已经实现过的逻辑,而低耦合,即模块与模块之间的直接连接要尽量低下,耦合性高,会导致牵一发而动全身,将导致未来的代码维护和功能扩展愈发艰难。

最简单的模块化即现在 Web 开发的 MVC 架构,数据库的建模部分由 Model 完成,页面展示由  Views 完成,而之间的协调和逻辑关系由 Controller 完成,以一个 Product 项目的创建为例,它会在创建时同时创建好另外两个字段的默认值 - Version 和 Component,当 Views 接收到用户的输入后,然后将它传递给 Controller,Controller 将会判断输入的合法性并同时创建好另外两个字段的类,再通过调用 Models 提供的方法将这三个类在数据库中持久化下来。

这需要在开发前定一套统一的 API,这样各个模块才能无障碍地随意调用。

那么这样的好处在哪里?其实是非常明显的,页面显示部分不用关注数据库会提供什么养的类型,而数据库也不用关注用户会提供什么格式的数据,都会因为中间 Controller 的调度和转化被统一起来,进而达到程序的模块化,以及开发人员的专职化。

以我自身经验为例,如果要和前端配合同时完成一套功能,我们会约定好我给他什么样的 Ajax method,参数是什么,返回的是什么样的格式,这样我们两个能够同时编写不同的代码,但到功能完成之时,将两个代码放在一起,直接就能运行起来。

SOA:

那么程序与程序之间的整合,使之同时完成一项功能如何才能做到?

传统的方法有提供 RPC 接口,轮询数据库或者文件系统,但是问题在哪里?

  • XML-RPC 同样会出现错误,而且缺乏 Error handler
  • 数据库和文件系统的轮询有很高的风险,首先轮询文件系统就以为着这个目录里的文件要小心放置了,因为不小心就会被程序轮询到,而因为轮询造成的数据库损坏的可能性更加难以纠正。
  • 很低的内聚性,很高的耦合性,为了同步两个程序间的数据,可能得克隆一份对方程序里的数据结构和逻辑方法,一旦任何一方的数据结构或逻辑改变,将导致同步失败。
  • 不实时,因为轮询总是有时间间隔的,轮询频繁会导致系统负载加重,轮询频率低了又容易等待时间过长。

那么程序之间的整合如何才能更好地做到,这就需要将 SOA 的思想引入进来了,SOA - Service Orient Architechture,面向服务的架构,程序与程序之间不再是程序,而是一个个的服务,这个服务可以通过 RPC 来实现对自身方法的调用,但是还有很重要的一点,是要将自身正在做的事情告诉别的程序。

下图是 Nitrate 项目目前的结构,其实我觉得它是模块化开发的一个典范了。

Nitrate 是标准的 MVC 架构,我来解释一下它的工作流,除了基本的 Web UI 界面和 XML-RPC 界面外,我们还提供了 Global signal processor(后简称 GSP)用于监听所有 Models 的信号,目前信号有三种 - Initial,对应于数据库的 SELECT 语句,Create 对应于数据库的 Insert 语句,Update 对应于数据库的 Update 语句,所有被注册的 Models 一旦发生以上动作将会出发对应的信号,然后 GSP 将信号推入 Plugin support(后简称PS),由它以线程方式将 Signal,Models 和触发消息的 Model Instance 交由 Plugin 处理。

这里我将 Plugin 分为了两类:

一类是 Special plugin,用于整合一些特殊的程序,这些程序不带有消息队列支持,它是以传统工具整合方式工作的,接受到信号后会根据已经定义好的参数判断信号是否符合条件,如符合则通过该 Special 程序提供的 RPC 接口将 TCMS 中的改动同步进该程序中,事实上该方法危险性较高,而且需要将对方的数据库表格和参数定义在插件里。

第二类是 Messaging queue plugin,这是我最偏好的方法,目前支持的 Messaging queue(以后简称 MQ)是 QPID,它将 Models 的 Signal 转译成 MQ 的数据格式,然后直接推入 MQ,然后别的需要 Nitrate 数据的程序可以提供第三方的一个 Sync middleware,作为两个程序间的桥梁对数据进行选择性的同步,这样的好处是逻辑不用重复实现,双方共享的数据之需要存在 Sync middleware 程序中即可,不影响双方逻辑和数据库结构。而 Nitrate 本身也提供了 TCMS Messenging listener 用于监听 MQ 内的 message,例如如果 Bugzilla 新创建了一个 Product,Nitrate 将很快便能监听到并在数据库中创建一份相同的 Product 供用户使用,全程自动化,智能化,无人干预。

“能听能说”的程序才能较好地整合到其它程序中,“听” 提供了 XML-RPC 接口,别的程序可以通过它更改 Nitrate 中的数据,“说”提供了 MQ 的支持,别的程序可以监听 Nitrate 中数据的变化,并以此为依据对自身数据进行添加、更改,而且不用存储对方数据表,不用了解对方的业务逻辑,只需要写好中间的 Sync middleware 即可,好处多多,其乐无穷。

测试驱动

在之前的 Scrum 培训总结中,我说到了 CI(Continuous Integration)是 Scrum 所要求必备的,那么为什么单元测试如此重要?

下面的图可以充分说明这点:

尽管手工测试可以降低编码时间,但这也仅仅是在项目非常非常小,而且没有后期维护成本的情况下。从上图可以看出,在第一个迭代的时候,开发如果和测试的时间是一样长,这或许可以生产出一个高质量的产品,但是到第二个迭代的时候,开发人员仅仅向软件中加入了很少的 Feature,但是测试却不能减少他们的工作量,依然要进行一遍完整的测试,而且还要检查是否有因为新加入的 Feature 导致的 Regression,到第三个迭代的时候开发的时间更加少,到第五个迭代后开发已经完全没用了,尽管测试占用的时间比例很大,但是依然无法保证测试完成,产品推到生产环境下会发现问题多多,开发人员就成了救火队员,下个迭代可能要用整个迭代的时间,去修上个迭代造成的 Bug,软件将停滞不前。

那么针对不同类型的语言和软件类型,有什么 Unit Testing 的方式呢?

这要从语言的类型和特点说起了。

* HTML,CSS - 前段,结构远远大于逻辑的语言。因为浏览器的兼容性问题,它是最难进行自动化测试的语言,但是依然是有办法的,可以使用类似 Dogtail 类的自动UI点击程序,判断 Console 中的错误输出,或者使用 W3C Validator 一类的工具,对它进行错误判断。

* Python/PHP/Java - 后端,结构和逻辑并重的语言。其实它是最好编写 Unit testing 的语言,因为它只负责一件事情:提供 API 供调用,我们只需要模拟输入,判断程序是否会出现 Error 即可,Django 提供了很好的 Unit testing 框架,可以模拟客户端的提交数据,以检测 Views 和 Controller 能否正常工作,Models 能否对数据库正常读写,或者 ForeignKey 的正确性也可以通过 UT 进行验证,Java 也提供了 JUnit 等工具。

* Javascript/其它 UI 语言 - 前端,结构和逻辑并重的语言。这是最有意思的地方,很多人说 UI 类的语言的 UT 非常难以编写,因为无法验证最终的正确性,其实仔细观察就可以看出,这类语言,其实只是调用了后端提供的 API,也就是说,对于此类语言,一检查提供给后端的 API 的参数是否正确,二检查能否将后端的返回正常生成数据结构并反应在页面上即可。前者依然可以通过检查后端的出错情况,而后者可以通过更改编码方式,将逻辑层和显示层拆分解决,例如后端返回的数据需要生成一个按钮,只需要将生成按钮的代码拆分,并通过单元测试检查按钮是否正常生成并符合条件即可,因为只要能正常生成,基本上现实在页面上不会出太大问题,这是基本功能了。

另外说一句有意思的事情,前两天听说了另一种 UT 的方式,名称叫 Monkey,写一个程序在屏幕上随机乱点,只要程序能稳定跑上几个小时就算通过,这来源于让猴子敲键盘,总有一天能敲出莎士比亚全集的传说。这也算是很有创意了,只是我觉得这不能叫 UT,可能只能叫 RT(Random Testing)了,缺点很明显,一是无法针对某个功能,二难以重现(可重现的 Bug 对开发人员很重要),三难以统计。

Posted by K*K Mon, 27 Dec 2010 01:36:18 +0800


Python 技巧:@classmethod 修饰符

通常情况下,如果我们要使用一个类的方法,那我们只能将一个类实体化成一个对象,进而调用对象使用方法。

比如:

class Hello(object):
    def __init__:
        ...

    def print_hello(self):
        print "Hello"

 要用 print_hello() 就得:

hlo = Hello()
hlo.print_hello()
Hello

如果用了 @classmethod 就简单了。

Posted by K*K Fri, 06 Mar 2009 01:44:28 +0800


介绍个不错的编辑器 - e-texteditor

换到 Windows 后一直找不到感觉良好的编辑器,从 UltraEdit 到 EmEditor,把 EmEditor 用了一段时间,可是各个编辑器都有自己的特点,始终无法感到称手。

直到碰到了 e(不是 Linux 上的 enlightenment r17),总算找回了点 mac 下 textmate 的感觉。

e_mainwindow

该编辑器几乎就是 textmate 在 windows 上的克隆,操作方式和使用方法几乎完全一样,界面也是相同的简洁,同样有着 mac 操作的优雅。

在 File 菜单中点击 Open Dir as Project 后,还可以通过 Settings 对 Project 中的文件进行过滤:

e_proejct_settings

对各种编码的支持也是非常强劲的:

e_encoding

查找和替换和 Firefox 一样位于窗口下部,而且连行为样式都完全一样,但支持正则表达式(最舒心的地方之一):

e_search

后退功能异常强劲,甚至可以分出两支来做不同版本的恢复:

e_undo

TextMate 最强劲的 Bundle 功能,E 编辑器也完全照搬过来了,甚至可以和 TextMate 共享 Bundle,直接从 TextMate 网站上下载新的 bundle 即可直接放入 e 中使用。(据说 e 的作者和 textmate 的作者是老乡 -_-#)

e_bundles

按下 CTRL ALT T 键即可唤出 Bundles 窗口:

e_bundle_item

一些小技巧:

  • e 也是支持语法补全的,只是要按下 ESC 键
  • View 菜单下的 Web Preview 对 Web 开发者调试静态页面很有用
  • 如果发现 e 不正常换行,可以在 View 菜单下的 Word Wrap 下调节

更多截图可以去:
http://flickr.com/photos/xuqingkuang/sets/72157605641477669/

下载可以去我的 Box:
http://www.box.net/shared/unhobn6gco

Posted by K*K Mon, 16 Jun 2008 23:19:00 +0800


UTF-8 的 Xoops

Xoops 是一套用于快速架站的 CMS 系统,以大量质量优秀,而且功能完善的模块著称。
除了官方的 CBB 论坛模块,还整合了 Wordpress 作为 blog, MediaWiki 作为 Wiki,台湾甚至有人做了 Xoops 的课程管理模块。

Xoops 刚刚获得了 sf.net 的开源社区第一届大奖赛中在所有的CMS系统中荣获开发类亚军,该组冠军为著名的Gaim项目。
有很多使用 Xoops 的社区在活跃着,包括大陆 Mac 界的麦客一班勃麦堂使用的都是 Xoops,Linux 界的社区的发行版 - CentOS 主页使用的也是 Xoops。

以 mambo 等其它 CMS 不同的是,Xoops 不是简单的 hook 似仅仅是账号的整合,而是从界面到内部模块之间都进行了整合,除了账户是通用的,模块之间的内容也可以互相调用。

因为工作关系,目前正在做 Xoops 相关的工作,将 Xoops GB2312 整体转换成了 UTF-8,在这里放出:
http://homepage.mac.com/xuqingkuang/FileSharing1.html (五月之前暂时别访问了,这个月竟然超出了 10G 的流量,详见抱怨帖

本版包含了一下模块:
  • Article 文章管理模块 0.9
  • libldap LDAP 模块 0.5
  • liens 联系我们 1.0
  • mediawiki 维基百科 1.63
  • MyAlbum-P 相册 2.86
  • Myiframe i框架 1.4
  • CBB 论坛(NewBB) 3.0.1
  • News 新闻 1.42
  • PrivateMessage 私信 0.1
  • Profile 账户管理 0.1
  • Protector 攻击防护 2.56
  • SiteMap 网站地图 0.7
  • system Xoop 系统 2.13
  • MyTinyd0 用于嵌入 HTML 2.22
  • WF-Downloads 下载 2.05
  • WhatsNew 最新内容 2.02
  • Wordpress 博客 1.63
  • XoopsPoll 投票 1.0
所有模块均包含了 UTF-8 中文界面。

因为 Xoops 对 PHP 和 MySQL 版本要求较高,建议使用 XAMPP 快速服务器包 1.4.10 使用,其它版本皆有各式各样的问题。

http://www.apachefriends.org/en/xampp.html

Posted by K*K Sat, 29 Apr 2006 15:17:00 +0800