TUP第七期架构师沙龙现场演讲实录

2011-01-05 16:27 | 次阅读 | 来源:未知 【已有0条评论】发表评论

关键词:开发工具,web开发,电子商务,产品设计,性能优化 | 作者:武力 | 收藏这篇资讯

11月27日,由CSDN和《程序员》杂志联合策划组织的TUP第7期活动首次来到上海,本次活动为架构师沙龙,邀请到了盛大创新院产品开发部研究员赵劼、《简单之美——软件开发实践者的思考》作者倪健和上海博科资讯技术支持中心经理周志军,为大家带来框架设计思想、.NET异步编程与用户自主架构方面的分享。

盛大创新院产品开发部研究员赵劼演讲实录

盛大创新院产品开发部研究员赵劼

刘江:我是CSDN&《程序员》的总主编刘江,今天从北京过来。来到上海感觉挺热的,感觉确实不太一样,我先给大家介绍一下我们这个活动,先调查一下,通过CSDN来的哪些呢?还是比较多。还是非常感谢大家,我们这个TUP活动第一次来上海,今年办了很多期都在北京,上个礼拜在天津办了一次。活动的理念是CSDN的创始人蒋涛想出来的想法,CSDN是全球最大的中文技术社区,注册用户没有任何其它的网站可以和我们相比,GLI可能只是三分之一到四分之一,但已经是第二大,我们的用户数肯定是全国最多。

大家也知道CSDN还出了一本杂志《程序员》,包括也做大会,12月9、12月10号有一个软件开发大会,以前一直在北京办,今年也是第一次来上海来,包括公司有安排的话每年会有一些技术培训,其实这是一个很好的机会。今年以来很多高质量的技术大会越来越多,我们当初是07年办的,是在软件开发方面最全的,而且确实是很实战性的会议,规模也一直比较大,去年还是最大的,但是今年我们办了一些其它会议,规模其实更大一些,所以今天不能说它是最大的。如果大家公司有技术培训的项目可以选择,因为去了以后可以发现主题很多,你可以学到很多方面的东西。像我们今年5月份办了中国云计算大会,确实有一些比较热的点。

CSDN以前是网上的活动多,有杂志,也有千人以上的大会很多,但是规模像今天这样几百人的,今天其实人也算比较多一点,在北京有一次500人,以后每个月的交流少一些,主题可能会更专注一些,这方面我们以前做的工作少一点。我们之前也看国外有一个网站叫TED,也是通过请各种各样的在各方面做的经验比较多的人,主题很广泛,然后来做演讲,我们就想是否技术方面可以做一个。后来我们策划和酝酿了一下提出了TUP,概念就是T、U、P,大家在一线做的时候发现尤其是现在很多新的趋势,像移动平台等等,你现在做的东西可能是相对比较小的团队做产品。不是以前一个很大的,我们做技术好像产品这个概念和我们没有什么太大的关系,就把技术下面的模块实现就可以了。现在团队更敏捷、更小,是一个以产品为中心的团队,而且你怎么考虑,你最后的成功,你公司的成功和你团队的成功不成功实际是产品的成功说了算,所以我们提出以产品为核心。

产品要成功实际有两个最核心的东西,一个是技术,一个产品的东西做出来以后稳定性不行、可靠性不行,性能不行,很慢,这都是技术人员要解决的问题,还有很多功能方面,包括测试等等很多,那你肯定是无法成功的,很难想象会成功。当然互联网产品可以很快去改,永远BETA版,每天发布不同的版本,这些是每天都可以实现的。

另外仅有这个也不够,现在最火的公司是苹果,当然他技术也非常强,但是他的优点可能胜过其它,包括GOOGLE这样的公司,就是用户体验。现在有很多公司其实US方面的人员也多了起来,包括用户研究、产品经理、产品设计,所以这是研发以前,整个从技术一直到研发的环节,包括还有一些研发的管理方面。我们以这么一个圈子为中心做了一个TUP,我们想做一个品牌,理念就是分享产品研发背后的技术和用户体验故事。当然用户体验现在的主题相对少一些,之前我们回顾一下,现在有两个系列,一个是系列是TUP,希望三个讲师,最后还有一个简单的QA环节和圆桌讨论。还有一个系列叫对话大师,我们已经办了两期,是把世界级的,当然国内也有很厉害的人物。当时我们请了UML的创始人,他也有很多其它的贡献,已经70多岁,最近又提出一个新的理念叫SEMAT,他觉得回顾历史,因为他资格很老,有些理念我们早就提出来了,就是一个很老资格的大师级人物。他说这么多年来软件工程涌现出很多所谓的新方法,包括从RUP、CMMI,这个像时装界,他说这个不正常,大家要寻常共识,如果对软件研发流程有兴趣可以关注一下,还是值得看的。

第二期的大师是请了WEB开发之父,不知道他有没有结婚,他是84年出生的,大二的时候就开发了jQuery,非常年轻,当时中国公司的宫力也是他们的董事长之一,所以人是需要梦想的,你看人家大二,确实人家有实力。

今年还办了其他架构方面的活动,第一期在北京请了新浪微博的首席架构师,大家如果做后端可以看他的博客,叫杨卫华,他的博客质量非常高,还有人人网的张铁安,还有百度贴吧的王鹏云,大家有兴趣可以上我们的网站,里面都有历届的回顾和实录。我们视频频道也会陆续把录像整理出来,大家也可以关注。

下面一步除了现场的演讲以外,我们视频方面也会加强,因为之前视频有牌照的问题所以停了一段,最近解决了。今天时间差不多到了,我先介绍今天的讲师,第一位是赵劼,是盛大创新院的研究员,和我比较熟,也经常在《程序员》杂志上写文章。我认为他是一个旗杆,大家如果做这方面可能都知道,因为他在博客园也很活跃,很喜欢跟其它平台的人叫板,因为很多从微软平台出去了,他老觉得微软以前的WINDOWS系统不好,又容易崩溃,老是感觉微软的产品是比较弱的,还是JAVA这些比较强,就很鄙视微软。赵劼是少数经常在应战,我就是比你们牛,至少不比你们差。我觉得是非常好,也很乐于分享,赵劼各方面对新技术和新话题研究得非常多。

第二位是倪健,刚才他自己介绍工作17年,也是非常资深,17年还是比较少的,在座的有比17年还要多吗?看来没有敢叫板的。倪健之前写了《简单之美》,确实把自己工作这么多年的思考写出来,我觉得内容还是非常好的,今天也希望他能够从架构方面讲出更多。

第三位是讲师是周志军,他是博科资讯的,你们两个其实讲的都是企业级开发的话题,我相信大家应该会有很多收获,等一下当然你们演讲之前也可以更多自我介绍一下。

我们下面第一个就欢迎赵劼!

赵劼:大家好,刚才刘江老师给我的说法不对,我其实公开叫板某一些有问题的方面,我不会随意公开叫板,为了某个不可告人的目的做一些所谓的挑战和挑衅也好,否则太容易被人驳倒。

今天我讲的是一些关于异步编程的演变,主题是这个。先介绍一下我自己,这是我的一些介绍,看一下最后,这就是刚才提到的我很痛恨Java这个语言,而不是这个平台,我是有目的地针对一些东西,比如Java这个语言,而不是Java这个平台。

    这是我今天要谈的一个话题,一个是为什么要异步编程,因为异步编程是现在趋势必然发生的事情,比如说云计算,云计算我们不是在同一个进程内搞,分析是分布式的,在互相的通信当中肯定以异步来讲,伸缩性或者各方面都比较好。还有WEB,我们任何一个异步操作,用户交互或者其它一些事情,等会儿会更多提到都是异步的。移动设备,我们的短信发进来都不是请求一下,看一下有没有短信进来,都是设备异步推给你的信息。包括现在好多的多点触摸,这些其实都是异步的,都不是同步的,大家可以想一下。

我们怎么来改进异步编程呢?这些其实都是很不容易的,因为这是异步的。我们怎么改善异步呢?我们提供新的语言特性,提供新的编程模型。在NET1.0是传统的模型,一种是Begin/End,还有一种是基于事件的,不具体做不知道这些指什么。这都是基于回调的,给你一个函数,用一个方法把这个函数调给你,不知道什么时候调的,但是异步工作完成之后不知道谁来调用这个函数,这就是回调函数,这都是基于回调函数的异步编程模型。异步就是这个意思,不是发出一个事件等你回来,而是发出一个事件做别的,等什么时候好了再得到通知,怎么得到通知呢?这就是回调,所以基于回调是很正常的,这就是最早,大概十年前一直到现在的异步编程模型。

看一下这个异步编程模型,分几个方面。首先有一个回调函数,这就是我刚才说的等这个异步操作结束之后再回调过来,Bgein/End分两步,一个是Begin,先放个函数,然后再回调,它会得到一个结果,大家不用关注太多,只要知道Bgein是需要回调的,就会得到这个结果,这就是一种二段式的,先发起,在列外一个地方得到回调。我们在浏览器上做编程的时候做得哪些事情呢?现在写一个方法,用四种方式来写,Transfer,给你一个数据流对象,再给你一个URL,然后再写回去。我演示的代码比较多,先创建一个,发出一个请求,得到他的,再使用循环不断的Read一些数据,再Write回,这是同步的方法。很容易理解,使用这种THINK就麻烦了,因为在这边要保留上下文。在一个异步的读写之后要,我还要对,这个异步的还要,我看有没有读完,没有读完再,所以过程是这样的。在这里要,如果读完了会不断循环读,读完了之后最终才返回。

我们刚才的调用很简单,如果我们要提高这段程序的健壮性,在异步的方法里就麻烦了,必须在每个方法里做出,因为我发布异步,回调一旦抛出没有捕获抛到哪里呢?可能就抛没了,我们目前的运行环境就会引起整个进程的崩溃,因为我们的回调函数是在另外的线程里面调用,在默认情况下会引起崩溃。我们的逻辑里都是try  catch,  大家看出这是很麻烦的事情。

还有一种是基于事件的异步编程模型,就是一种更加典型的基于回调,我会准备一个event,我先监听事件然后发起,等它异步操作结束之后会发起这个事件,就会得到一个异常或者是结果,你判断到底是异常了还是结果了,是出错了,还是正常返回。但是并没有改善任何的状况,还是基于回调,这就像浏览器上一样,我们send以后事件不断发起,可以看到这么一个状态是怎样的。这就是基于事件的异步编程模型,不管是怎样都给我们带来痛苦的编程体验,我相信肯定有进行一些网络通信的朋友认为异步编程很麻烦,一比就觉得异步编程比同步编程麻烦很多。

为什么会麻烦呢?非常关键的一点就是代码的逻辑局部性被破坏了,我们在同步编程的时候想要做条件跳转,想要做循环,想要调用一个操作直接调用某一个方法,方法结束就把结果交给我们,我们就可以继续用下去,非常简单。这叫代码的局部性,作为程序员很常见把一个算法使用线性的方式表现出来,刚才说的语言的构造元素都是线性的。如果把这个操作异步化,我们不能用这些东西了,像刚才一个好好的操作变成了,我们的代码被拆得支离破碎,我们必须把这些线性的逻辑拆成很多,这给我们带来很大麻烦,本来参数直接用,一些局部变量不可以直接用,但是现在拆成了多个方法,那些参数怎么用呢?局部变量怎么用呢?我们不得不看一个对象,用其它的东西把这些上下文保留下来,然后在另外一个方法里访问上下文。先发起,再完成给我们带来很大麻烦,我们的上下文必须手动保存。

作为这种方式我们很难进行异步操作的组合,我现在举一个例子,我现在在浏览器上有一个动画操作,有一个淡入、淡出的操作还有获取外部资源的操作,你怎么把两个操作并行起来,两个操作同时发起,等最后那个操作结束之后再整个进行下面的逻辑。如果是线性的话可以用异步串联起来,如果是同时的呢?有的时候A先结束,有的时候B先结束,这部分逻辑怎么写。我们同样因为异常处理和异步方法的取消是很困难的,我们同步方法的取消只要在某个地方判断哪个设计设了标记取消,直接break掉就可以了。在异步方法发起,没有回调的时候怎么取消呢?我们试着开启一个线程然后再关掉,这可能会引起难以确定的问题,我们怎么取消呢?出错处理、取消和组合这些异步操作都是很困难的。如何解决这些方法呢?到了NET2.0和C#2.0,多了这么一个关键操作——yield  return。我想很多朋友Java里面写一个()是多少麻烦事情,判断有没有以及把什么指针往后移一格,用这种方式构造一个竖立结构。

在1.0和Java里写起来是一样麻烦,到了C#2.0有了一定的改善,像这样的方法是一个迭代器,就会做这样的事情,当外部代码第一次调用的时候代码会执行到上面的一部分,直接返回出去。项目代码可能不执行了,可能以后再执行,这就是MoveNext,再执行下去就是最后的一段代码。我们用线性的逻辑表现出来,如果不用这个1、2方式会怎么会呢?如果第一次调用我们返回零,第二次调用返回一,第三次调用返回二,真实情况下可能有一些清理的代码,关闭一些资源,表明已经没有一些剩下的因素,这就是依次推出的方法。

这和异步编程有什么关系呢?这就涉及到这一块怎么实现的,这是编译器帮你拆成支离破碎的变量,然后看你是调第几次,如果是第一次执行这一段,第二次就掉这一段,利用这一点我们怎么辅助异步编程呢?这段代码可能比较小,但就是完整的异步方法,原本需要几百行代码直接贴在PPT里已经是很了不起的事情了。我们在这里有很多方法,这些方法都是在发起BeginRead,这是一个比较出名的人做了辅助类,他的工作就是协调异步方法的Begin和回调操作。我们已经获取,然后,什么时候再执行下面的代码呢?控制权已经交给外部了,下面的代码等下一次调用MoveNext时再执行,会等异步操作结束之后再调用下去。下面的代码可以直接调用,我们可以使用Using进行管理,等回来的时候可以像刚才一样,如果需要break可以跳出。根据这个循环的构造又会直接到上面去。

这么做有什么好处呢?保证了一点,我们可以用平时最喜欢的线性逻辑来实现整个异步操作,这就是yield,下面的代码就会在异步代码结束之后才结束,好处就是得到更好更新的编程模式,可以让我们使用。

到了NET3.0没有什么大的改变,F#是强类型的静态编程语言,生产率很高,Java的生产率不高,有的时候有人感觉动态语言生产率就是高,其实并不是,只是利用函数是编程的概念用到里面。带有一个面向对象的编程能力,他是一个开源项目,这并不是指开放原代码,一切都是Apace2.0,除了工业使用之外还瞄准了教育界,已经在很大大学里作为教育使用。微软也知道一旦作为教育必须要开源,否则很难研究内部,就不会在教育内部使用。

还有一点必须要跨平台,Apace跨平台是由微软支持的,在今年他们的研发团队来到中国,我和他聊的时候他说这个跨平台主要的工作是修补,跨平台是微软自己提供支持。

他解决了这么一些并发的挑战,一个是不变性,只要不变就不会有编程当中的竞争。代码的局部性、L变形,还有一些使用并发机制都是涉及到。

一个语言不应该只针对一种并发模型,应该针对各种并发模型,Think就是这样的模型,Let!把3复制给A这个变量,当然这不是变量,因为是不可变的,只是常量。Let!是个React!下面的代码会异步操作返回之后再进行。这个异步操作可以是请求,可以计时器的回调和数据库查询,一个文字写操作的回调,甚至发出一个消息,一旦发出消息就继续执行下面的代码。

我们看到这些都是Let!use!带感叹号做的都是异步操作,都会在异步方法结束之后再继续执行。这些使用一些很简单的一些扩展机制,帮你变成,用这种方式我们可以用循环也好,当然这里不是用的循环,是使用递归的操作。

为什么他能做到这一点呢?关键还是在编译器,我刚才说要解决异步问题一个就是要引用新的编译器,代码就是一种文本,编译器多了一种文本就是多了一种语言特性。Let!img=AsyncRead,回调以后再调用接下来的,到用一个异步写操作,再通过一个异步操作回来。

由于时间关系,本来还想谈一种编程模型,但是这种还是多强调一点,首先是内库,不是语言特性。Async  Workflow不是语言特性,把刚才的线性逻辑变成这些回调,他是支持这个语言提醒实现的。它可以支持所有其中的语言提醒,还有If/use,很方便进行异步模型,可以组合异步的操作,还有接下来就是异常处理和取消。

这本来是我想讲的,但是时间有点不够,NET4.0,也是盖布了异步编程的模型,它的做法是根本性改变了你对这种异步操作的看法,为什么能够这样做呢?因为他是告诉你异步运算是推的集合,用户不断点击鼠标,其实相当于不断发起一个一个鼠标点击事件,一个集合会有不断的鼠标点击事件,用户的鼠标在界面移动是一个事件,一个异步的请求会在某一个时刻推还给你。

为了这么一个过程有一个交互式编程模型,我们把它对偶一下就变成了一个推的编程模型。在使用方面已经用到很多方面,有人说LINK就是一个ORM的框架吗?这和ORM和数据库没有任何关系,我们把一个异步事件当做。

在Wap上的编程所有都是异步,刚才你们看到是一些,可以在服务器端使用,这就是刚才的版本,就是我一边大字一边查询,一旦停了0.5秒,向服务器端进行请求,得到结构,我们不断打字不会发出请求。这里也是这样的,我待会儿可以演示给大家看这几行代码所形成的效果。

好处是什么呢?还是协调组合异步事件以及能够更好,比较简单地来表明这种线性的算法,For/While都是不同的方法,我们可以很方便地塑造一个异步的集合,然后往里面准备好,这个要五个元素,看你怎么处理,这就是单元测试的方式。

只要是现代的语言,有一些基础的,有了这些功能以后要实现就很容易,但是几乎不可能在Java里实现,Java器已经分成了A和B计划,最后使用的是B计划,所以还是在不断推后Java的进程,所以Java是一门生产力低下的语言。

我接下来要做一个演示,先做一个比较,F#  Async  Workflow和Reactive  Framework,很遗憾必须要学习一种新的异步编程模型,你能很好接受的话自然没有任何问题,但是如果你接受不了就要新的学习代价。

这是很有趣的演示,我做一些简单的代码给大家看一下,先给大家看一些事例,这个实例很土,就是一个时钟在这里走。打个比方现在已经有一个辅助方法,你给出一个时间可以在上面画出时钟出来,给你的话你会怎么写这个代码呢?大家看一下这边的代码是怎么写的,我使用的方式是while(true),然后是drawClock。注意这里有一个特点,我做了扩展,表明了这是一个异步操作,接下来的Jscex.Async.sleep,接下来的逻辑会在异步方法结束之后继续执行。为什么可以得到这种效果呢?因为我利用了拿到一个方法,可以得到整个方法的代码,得到这个代码之后把它解析成语法数,我在这里可以看到在这些,我把这个去掉,去掉的原因就是不想把这个代码显示出来,如果把这段代码显示出来的话开一个记事本,我们把两个alert去掉,保存,重新刷新。用了这种方法,我们写代码像写普通的一样,可以不断往下写。你想让它停顿就sleep,你想做其它事情就不断做,它有什么好处呢?我还准备了另外一个例子,当时我说了有一个异步方法其中一部分是动画,这个动画实在是太土了,但这个动画是怎么写的呢?我们如果让你写一个移动图形的方法会怎样做呢?您肯定也是先用,因为只有一个方式,每50毫秒做一下下一步操作,但是我在这里使用的是一个for循环,改变了一个操作,休息50毫秒,改变一点,休息50毫秒,我做的还是这种方式,它的结果就是调用它,你就会看到刚才蓝颜色的区域从左往右移动的效果,调用一遍,这个红的这么绕一圈是怎么做的呢?红的绕一圈就是移动4次,所以接下来move Square。这里再给大家看一下调用使用回调是什么样的。这里有个注释,可以把它去除。

这就是刚才四句的方法,但是在这里重新编辑成为这种,我可以得到所有的代码,拿到重新解析成语法数,组装成新的代码就是新的方法。可以看到,我们现在发起一个异步操作容易很多了,组合一些异步方法有了。

这部分逻辑放了一些初始代码,但是我还会进行修改,接下来我的相当一部分精力会投身在,我想异步编程的内库会是比较重要的东西。关于这个话题应该也会在下个月在杭州的前端会议上进行谈论。

我其实不算是典型的简单开发人员,我不涉及任何样式方面的东西,因为样式太复杂了。Jscex&Jscex.Async,这就是动画的代码,这就是典型的编译器过程。在下一个版本里面对异步有更好的支持,这个更好的支持还是在编译器上做手脚,它的做法就是多了一个await,不用看懂这段代码,我也没有完全看懂,自动生成代码就是这样。这么一段简单的代码做的是什么呢?得到client,然后再解析、返回,它的语言逻辑和我们刚才提到的关于异步编程原理是一样的,因为是重新修改了代码,真正翻译过来的代码不是这样的。我们写的代码是简单的,生产的代码是复杂的,这是以后要做的事情。

作为结论,结论是很难的,但是我们引用新的编程方式来做到这点。

难以调试这一点很有意思,关于这一点我可以谈一些我的看法,Jscex是编辑成很常见的,执行一步回调,两种操作方式互相组合。刚才写了Jscex难以调试,但是可以调试,只要在代码里放上就可以调试,只要在这个把这段拿出来,这台机器上应该没有。

这段代码其实并没有实际的那么困难,大家还有什么其它的问题吗?对于Jscex调试不是很了解,但是对另外一个方面有看法,就是效率问题,在IE8的引擎效率已经比较高了,我不担心,IE8也可以接受,但是IE6和IE7比较难以接受,我们重新生成的一些代码效率肯定比现成的代码差。它这段方法是更好地利用了效率,但是通用性更差,如果真的出现了问题,有出现效率问题,可以马上用状态机的方式编一下可以同样作用,关键可以拿到代码生成新代码和新方法,这是最强大的一点,所以效率方面也不是没有解决,现在引擎的效率实在太高了。

还有什么问题吗?在我上一次举行的会议也是,就是把有问题直接放在上面,收集以后马上进行问答,不用提问。

《简单之美》作者倪健演讲实录

《简单之美——软件开发实践者的思考》作者倪健

 

倪健:先谢谢大家。

我很少参加这种活动,大概99年参加过一次,那个时候刚开始进入企业,做这种企业应用软件,有一个产品发布的时候也是我去介绍和演讲的,那个时候做Java的很少,jsp还没出来。

我稍微介绍一下自己,我是93年毕业的,毕业以后主要做单片机编程,然后做了几年以后来到上海做电器控制柜,就到现场布线和拧螺丝、布管道这些。98年开始做企业应用软件,最开始做VB,后面是学了Java,后面也用C++。今天主要介绍一下设计方法,不是一些技术的细节,当然里面也会涉及到,主要偏向于设计方法,包括设计方法的思考。因为这种方法和思考在企业应用软件当中是非常重要的,因为我曾经就职过这类企业,他们厂商很大,项目很大,一个项目可能上千万美金,但是做的里面的东西还是有一些问题,所以今天可能会稍微带一下涉及到的问题。

今天介绍的有两点,主要是前面一点就是软件的设计方法,当然也涉及到设计决策,因为这个很重要。一些设计决策对你企业的系统的构建影响非常大,可能带来一些灾难性的后果,这些后果只有你经历过、设计过、做过这种大型的项目可能才会体会到。

这是在软件架构工程书上的一句话:软件构架源自何处,当然是来自设计师的聪明才智。究竟是怎么构想出来的,我们外面卖很多书,里面讲怎么做软件构架,里面有一、二、三、四,但是拿到这些去做软件构架是远远不够的。唯一相关就是和设计师的聪明才智有关,和你人有关,和大脑有关,你的经验,你的思想,你的软件开发的思想有关。这种思想要有一个比较长期的过程,然后慢慢会形成一些开发的思想,这种思想可能你在做软件的时候,做各种设计决策的时候,你的思想会影响到你的决策细节。如果你没有思想,只是看到哪里,或者听别人说到哪里,你在做决策的时候很可能是错误的,以后没有纳入到你系统中去。

第一,稍微介绍一下程序设计语言的一般性比较,我这里比较C和Java,下面会介绍软件设计的本质,这是我自己想的本质,就是实际上怎样可能每个人都不一样,我书里也经常讲本质,实际都是我自己认为是这样的事情。当然我自己很相信它,我在做设计或者一些事情的时候这些东西帮助了我,我觉得自己有任何问题对我来说没有什么障碍,就是在设计方面。当然在我所在的这个领域,在不同的领域我欠缺这种领域知识可能不行。下面再介绍一下软件设计当中的一些输入因素,再介绍一下软件框架的设计实践,我会介绍这次设计从最开头一直到最终东西出来,当然是个比较简单的,或许复杂的东西这里没办法涉及,但是这个过程是怎样来的,大家只看到有东西出来,这个是怎么出来的,经过了哪些步骤,不是拿了一本书一、二、三,或者编写了一段代码就出来了,不是这样的。再下面介绍一下设计师的素质,也是我自己认为应该具备这样的素质才能成为好的设计师,最后简单介绍一下设计决策,可能会简单提到几个例子,在实际工作当中碰到的例子,说明设计决策的意义。

这里是语言,其实我对语言不是太关心,因为我本身不是做语言这件事情,不涉及语言本身,是要应用,感觉主要是用它,可能很多特性没有用到,也不是很妨碍的。做设计时最关键的就是创造,就是想象力,不是拿一本书就可以,你要有想象,怎么想,我们可以举一个例子。我们知道C是面向机器的语言,处理的可能是你在机器领驭的知识,比如说内存、一些地址,怎么在内存里面做一些运算,最基本的就是一个变量和函数,无非这两种。虽然C本身是很精炼和简单的,但是你用这个可以做非常复杂的应用,等会儿我们可以看一个比较有趣的例子。另外一种就是Java,java是面向对象,也就是领域,对所要的工作进行抽象。你可以把机器抽象到领域知识,一样可以实现很多东西,我们在企业应用中更多的抽象应用是企业碰到的行业业务知识,主要涉及一些类、字段、方法,无非是这些东西。

我们看一个简单的C程序。C程序是在C语言编程经典书里的问题,那个问题的解答在另一个习题,里面提到一个例子,他要编写一个程序,输入一个字符,里面的单词长度有长有短,这个长度我要把这种有长有短的字段做一个统计,打印一个直方图,在这里实现的是水平方向的,在真正的解答里是有垂直方向的。

这个C程序很简单,刚才也有做C的同学,可能我们在考虑这样程序的时候最开始脑子里思考的可能就是这样一个过程,限于这样的过程,实际对C理解非常透彻但可能做的东西不一样,等会儿也有简单的介绍。可能有一些初始化,这里可能是初始变量和单词长度,然后要对单词做一些统计,主要对竖组做一些填充和计算,计算一个基准,可能要有最大的程度,因为直方图并不是多长就显示多少,可能有一个最大值,其它要做一个比较,然后取一个比例。然后我们就去打印水平直方图,最后可能做一些其它的处理,比如说显示一些消息什么的,这个很正常。当我们拿到这个题目的时候就会想这样做,实际大家可以看这样的程序,就是按照刚才的那种思路做下来,得到了一个结果,我们录入了一个句子,就得到了这样的统计报表,这是一个简单的C程序。

当我们在企业应用环境中要去考虑类似这些问题的时候,我们要做一些扩展的想法,不局限在仅仅解决这样的事情上。

这个刚才遗漏了,刚才我们看C程序可以写得很复杂。这个是一次乱码大赛世界冠军的作品,里面用了非常多的符号,这里面有很多算法和嵌套,我没有看分析,网上有专门分析这段逻辑,没有有意思。实际上输出的结果很有意思,是一段很美的故事,讲了圣诞节爱人给他送的礼物,类似于这样的事情。我想表达我们可以把一些简单的东西表述得非常复杂,甚至在你看上去很简单,你看上去可能就是这么几行代码,但是里面包含的内容和想法非常复杂,可能一般还要分析半天。

还有一个也是讲简单复杂的事例,前面我看毛志超(音)老师写的分析,他里面对于Linux用了很多知识。

这里就是一个介绍,实际上这是在某一段代码下面的注释,介绍这个代码在做什么,但是他通过一种想象,在这种有场景的,你看到这里一点也不觉得枯燥,实际那段代码做的就是这样的事情,一个进程来到门口要票,发现门票已经发完了以后,只好到休息室里休息、等候,你在做程序的时候,很多情况下是有场景的,在这里组织的也是一些领域,这些领域可能对照的是一些机器方面的知识,你的结构通过这种方式表达出来。

我们现在考虑在企业应用环境下需要对刚才说的那件事情做一些设计,这个时候我们要展开去想象,因为大家等会儿可以看到有一堆代码,如果没有前面的想象过程,你只拿到代码就会感觉云里雾里,实际是比较清晰的结构。这个例子是刘江总编说要填一个例子,我就写了一个。

首先我们想象有一次打印服务,很简单,因为我实际写的那本书的名字叫《简单之美》,我认为很多事情很简单,你想清楚了就很简单,你没有想清楚就会觉得很复杂,等会儿我们又可以看一个很复杂的例子。一次打印服务,这次打印服务要做一些事情,我要有一些内容,然后这个内容可能先要做一些格式化,格式化以后就成为格式化后的内容,然后再去对这个内容做一些转换,转换以后有内容,对这个内容做一个装配,装配和展现形式绑定起来,最后有一个出口。这是一个大致最初对这个事的想象,但是每个人的想象不同,所以说设计没有唯一,每个人的想象是不一样的。

实际上你也可以看成是模板,我们叫流程,在这里我们对一些内容做一些细节的想象,比如说这里有内容,我有什么样的内容呢?有很多种,比如字符串,或者是单词这种形式的内容,或者是单词统计,甚至是一些文件,或者是文件表格,这些在企业应用当中是非常常见的,因为我的来源有各种各样的形式。这个内容会对应到有一个值,这个值可能有各种形式的,有些可能是字符串,有些是统计的信息,有些是单词,有很多种,你可以扩展开来。我要有一个格式化器,我要对内容进行格式化,因为你进入的内容各种各样,所以要有各种各样的输出,然后对这个单词的长度做一个统计,可能你也要有一个处理器,上面有更抽象的处理器,上面是单词长度统计处理器,这是一种特殊的处理器,我们当然也可以有其它的处理器。类似就是这种方式,你可以往下想,没有具体的,但是你的活动肯定会有很多,涉及到很多方面的知识,你需要做训练,因为你不仅仅看了刚才那个。

这里可能对它做一些细化,在最下面这个可能有点不清楚,就是抽象的内容,我有个内容,格式化器,格式化完了以后有格式化后的内容,然后再对它做一个处理,处理完了有一个输出内容,然后跟显示的展示内容绑定,然后再进行装配,最后完成打印服务。

想到下面是一些比较抽象的,我们再往上想可能是一些比较具体的内容,比如说我有一些字符串或者单词、列表形式,或者是做,反正你可以往外想,但是结构、模板和流程在这里描述。如果再细化还可以有一些不同的纬度和角度对它做一些描述,比如你要考虑一些活动图,考虑一些持续图,所以有很多知识。

这里就是经过了设计以后的Java程序,大家看这里有一大堆东西,因为你前面想清楚了生成这些东西是很快的,可能一天或者半天这个就出来了,因为你前面想清楚了他要做什么。因为每个里面的代码都很短,他输出的就是这样的,最上面这里是一个模板类型的处理,有一个输入,输入以后做处理器装配的用法。这个下面和前面实现的是一样的,但是这个设计可以做一些扩展,将来有不同的输入或者输出内容,你要转成不同的格式,你个展现方式又不一样,你要通过直方图或者是饼图这个结构就可以在这个上面做很多的扩展。

这是一种面向领域,整个的实现过程当中有一点是他没有考虑的,就是他的性能问题,这也是一般面向领域、面向对象语言的普遍特征。因为你的关注点是在对于领域的抽象上想做一件事情,这个时候不可能像前面考虑分配一块内存和竖图,做一些计算,有一些高效的算法,可能少地分配内存。

这里有一些思考,在企业应用中什么是比较正确的设计方法呢,不是意识流,不是你前面没有想过的,然后你出来一个东西。我们知道每个东西在那里都是有结构的,就算你意识流出来,就算通过不断的 尝试出来,或者因为各种原因,大家集中在一起都是有结构的。只是这个结构好不好,有没有有利于将来你对它扩展或者你要保留这个投资,你那个时候是否真正能够有用,还是大大增加了你的维护成本,你将来发展的成本。

我们看一个例子,这里看到有我一个同事,但是这个例子不是在PPT里面,只是简单给大家看一下。大家了解到的只是很复杂,但是你不是很清楚它里面在做什么。这个在做什么事情呢?就是点了两次按纽,而且点了两次按纽以后仅仅是做了点了两次按纽中的一部分,我可以说是30%左右的事情,因为比较偏前面的页面,最前面是浏览器,后面是后台,这只是30%的事情,里面用了12次活动的流转,而且基本上没有做什么事情,只是载入一个页面,大家可以看到它的复杂性,在一些大的系统里面会变得越来越复杂。

还有一个图,这个图可以结合刚才那个去看,是在那个图的后端,再往后做的一个事情,里面有很多的概念,有很多的层次,有很多的通讯,这是一种简单和复杂的关系,大家可以看到,虽然你说一个东西简单,但是可以做得很复杂,正确的设计方式就是思考。

有人可能会说这个是不是你做了过度设计。什么是过度设计呢?我工作的时间比较长,按照我的判断没有什么过度设计,因为很多人你可能没有这个能力去做过度设计,我碰到做了过度设计所以我要简化,实际他做的事情相当于没有设计,如果你有能力做过度设计才能判断什么事情是可以去掉或者什么事情可以保留,你可以做这个事情,大多数的情况我觉得不要谈什么过度设计,因为我们很多设计不出来过度设计出来的东西。

简单可能刚才也提到了,我们要怎么把刚才的那种结构去做简单化,实际在企业应用领域当中是非常重要的一个话题,怎么能够把我们刚才看到的这么复杂的结构,复杂的关系简化掉。

因为我们后面还会稍微讲一下,软件设计主要是这样一个工作,我们有商务的背景,有一些业务需求,但是我们还会有一些中间的过程,这个过程就是想象,这个过程就是做一些约束,这个是设计的中间过程。大家打交道最多是不断在这个来回之间去做对软件的框架、设计的调整,最终你可能产生一个结构图。这个结构图是我网上随便找的。

这里不多讲了,很多书上都有,你要去看一些背景或者是看一些业务需求、想象都有。

我们下面介绍做一些框架,这个框架本身是有一些特征的,这种所谓的特征、本质都是我自己的理解,这里的框架是一种隐喻,我按照某种方式,就是某种可能和我的客观世界、现实世界比较类似的一种方式去做一些事情。通常是这样的,大家可以去看很多框架隐喻基本都是这样的。他是一种隐喻,也是一种工作,我们希望好的框架是可以被替换的,只有可以被替换的框架才能够保留我们原来的价值,因为框架未来会有变化,我们和这个东西绑定了,将来你要保存下来,在新的地方重用就很困难。另外是一种规范,就是有一些必须遵循的编程模型。另外是一种服务,目标是为了给我们,让我们做一些公共的事情,不需要再考虑的。

这是可以看到一个框架,这里面有一些隐喻在里面,服务器等等,这里面是静态的结构,看不出关系,但是实际设计者是有想象的,一件事情进来怎么通讯怎么做,是比较完整的故事。在这里有一个业务需求,我也简单过去了。

我们说框架设计不是写业务用例,不是直接针对一件事情,要把这件事情描述清楚,而是在这种事情的基础之上去想一个运行的一些公共特征,也不是建模,抽象的一种工作模式。

这个是做一些初步的想象,我们可能去请求一种业务操作,这种业务操作可能有多个操作组成,可以划分为一些计算的规则,操作和计算单元可以进行配置,我们初步想象进行到这个的时候我们对后面的细节都不知道,我们只是对它有一个大概的设想他应该是怎样的。然后我们通过上下文建立一些动态关系、传递信息,信息应该是基于统一的对象模型,然后不同的对象模型有不同的操作定义,在开始之前我们还进行了一些条件检查,最后我们有个结果,这是一个初步的抽象。

我们可以得到一个初步的设计,包含哪些元素,这里也是静态的,做设计的时候大家可以进一步想象,做一些动态的。前面提到还要考虑做一些功能的约束,我们去考虑计算单元可以做一些重组,框架也可以提供一些服务,这里假设提供一种事务支持,框架也要支持上下文中信息的传递。框架的使用者基于操作组、操作和规则来表达业务逻辑,只能使用统一的对象模型,这对于你将来设计框架有帮助。因为你在做设计的时候要有很多材料,这些材料都是来源于外界的触发,你自己对它的反映,你反映的越多,设想的东西就越丰富。

你可以对它做一些进一步的想象,这也是一本书了,你想象通常是它的运行态,在运行的时候应该是怎样工作的,它的结构和你在静态时是有不同的,这是《设计模式》书上的一段话,基本可以考虑很大程度上是相互独立的。

进一步想象,我们就对框架的工作故事场景做进一步想象,比如用户现在做一件事情,这是已经实际工作了,他请求一个引擎,为此设立一个代理,我们可以了解一些引擎的信息就可以做。我们要真正做的时候可能要做一些初始化,比如读文件系统,类似于这样的一些事情,是一个动态的事情。但是在想象这个的时候,你生产不知道很多的细节,后面怎么去实现,怎么去做,你不用关心,因为你保守一定的原则,你将来做的时候这些都可以去解决。

然后可能做一些精细化的设计,这个时候需要使用到一些工具,在这里把前面抽象的内容全部通过建模建立起来,当然这是一个非常简单的模型。然后基于这个模型生成代码非常方便,很快,因为你想清楚了,知道它怎么工作就很快了。这是模拟它执行以后有两个条件,一个系年龄大于30岁基本保费加100元,这不是实际的业务。这里有一个测试,需要有一个例子,然后我们通过这个来处理这个任务。处理这个任务就可以得到一个结果,把这个结果打印出来,从对外你可以使用到它的是这样的一些。这里实际可以做很多的扩展,因为这里有规则,但是有很多规则的实现是可以对这个规则做扩展的。这里还有其它的扩展条件等等,或者是类似的操作信息,这个是可以运行的例子。

你可能还需要做进一步的考虑,这个时候考虑怎么处理多线程、安全性怎么解决、扩展能力等等,可能有很多进一步的考虑,针对这个框架。

这是我认为设计师的基本素质,一个是要做一些知识积累,可能你要有想象,要沟通,还要有一个决策的能力。设计决策的意义,我们知道在做一些企业应用开发的时候经常会有开发成本在某些时候突然一下子增加很多,而且经常性的,就是在维护将来对它做升级等等,有很多开发成本,什么决定了开发成本呢?在我看来,开发成本第一位的就是你做的设计决策,包括你要有一个因为好的设计决策带来好的结构,这是第一位的,然后才是需求变更,或者是其它的一些。这里只列了两个比较重要的,开发成本的第一位就是在设计决策,这些决策都在一些细节上,大家可能不注意,但是你的决定就会影响我将来,影响很大。我可以举一个例子,在以前的公司碰到的,我们一次页面上的按纽可以有数千次的数据库访问,就是点了一个按纽。为什么呢?我这里不细点谈,但可以讲牵扯到的东西,刚才大家已经看到一些东西,这个之后还有一些框架,还有数据库,还有页面上直接访问数据库,还有去循环,循环的时候去访问数据库,很多很多。这个带来很大的,你要针对这个要做性能优化,这里需要投入大量的人力去保证他,而且每一次都要碰到这个问题。在解决的时候你要花很大的成本和代价,因为每次只能对它局部,在非常局限的情况下做。

需要决策的就是技术选型和设计细节。设计细节也非常重要,就是刚才我们前面提到的,在我的书上也介绍了,有人认为最大的开销在于设计细节。决策的目标就是这些和你的成本有关,你为了保护投资,你必须去做这样的一些考虑,我们在做的时候是需要考虑这些内容,而不是要考虑使用什么工具和框架,还有什么语言,你考虑做的东西怎么用,你做的东西怎么可以移植,做的这个系统怎样可以伸缩,怎样可以扩展,这样是可以保护你的投资,以前做的东西就不会浪费了,否则你转换到一个新的东西,每一次这个变革有很多。99年GSPM还没有,这个过程中变化非常大,很多新技术和新概念,短短的十一年,但是这个过程当中有多少企业会在里面频繁升级,频繁做新的系统呢?很少。他们以前做的东西希望可以保留,所以这些是最值得需要考虑的问题。当然还有一些其它的,你要考虑一个性能问题。因为我们讲计算机计算提供给我们的知识就是高性能的计算能力。

这里是一些可能碰到的例子,比如我设计决策可能考虑使用,和某一种数据库平台绑定的技术,将来你就会由于将来的发展可能要脱离这个数据库,你无法脱离了。假如说你决策用这个,可能会丢失掉你的大单。另外对第三方组建的包装,你经常想到有一些新点子和新的想法,但是实际上很多第三方的工具、第三方平台、框架都是非常优秀的,你如果能把它用好就足够了。包括我前面说的框架,那是03年的时候我做了一个简单的小框架。现在看已经过时了,根本不需要这种东西,因为有DPM,去组合和串起一些流程,这里面可能还有很多分支,那个已经完全不需要了。

通过DI来解耦,几千次数据库访问来源于这个想法,我博客上也介绍为什么这个想法是错误的。

然后是要用Bean  Copy或者是某些工具,有些工具非常好,有些工具是有问题的,我在书里也专门提到这点。比如说类似于一些像JRules这样的东西,因为以前我曾经用过它,而且很深入用过它,那个时候碰到了很多问题,比如说我的规则的移植问题、我的语言的升级问题,都带来了非常灾难性的后果。因为当你要迁移成千上万这样一个规则,但是你基于的基础是你的对象模型已经发生变化,或者你描述这个规则语言发生变化,这些都成为泡沫。你要做大量的工作去维持你以前的投资,所以这个意义是很大的,可以通过一些简单编程模型就可以完成。

另外就是团队决策。我认为团队决策也是一个错误。在开发里面我们需要团队决策,但是是自组织的团队决策,很多时候团队决策只会带来一些妥协,最终的结果就是四不象,最终的东西根本不能反映任何一个人的想法。

我介绍就这些,谢谢大家!

刘江:大家提两个问题。

提问:过度设计怎么理解,我们通常做设计的时候都是根据客户的需求来做的,我想了解一下怎么理解过度设计。

倪健:比如像敏捷方法,他经常说要避免过度设计,他需要一个迭代一个迭代去做。最开始只要做简单的,你不要想很多的东西,接下去在下一个迭代再想,但是真正能够控制这样一个过程的很少,至少我看到在敏捷方法里面这是做不到的。你最开始就是要好好设计,从头开始把这个事情想完整,你将来可以对它进行扩展。像我们刚才介绍的框架,其实前面完全可以绑定到这里,两个组合在一起就赋于了更多的内容。

过度设计通常是讲你做了不该做的东西,但是在企业应用当中这种事情是比较少的,用户的需求很多,关于需求的问题我在书里也有专门的一章。我们要比用户考虑得多、要完整,我们要告诉他们完整的故事是什么。我前面也说了,最大的开销不在于需求,而在于设计决策。在那样的结构下面,你任何需求的变化对他的影响都很大。但是如果你换个比较好的结构,简单的结构,我自己也做过简单的结构,他会给你节省成本,让你把精力集中在用户真正想要的东西上面。通常用户的要求都是比较合理的,很少有客户蛮不讲理,什么都要。但是很多企业都比较排斥用户有需求变更,你排斥是没有用的,相当于双方在这个问题上去战斗,最终两败俱伤。你有好的结构完全可以容纳客户的想法,像刚才说的,如果我有那样一个结构,一变可以变成饼图和水平图,如果事前不想好就要重构。如果有很多现有的实现完全基于原有的结构上,你的变化就会很大。

这是我的想法。

提问:您认为领域知识在设计中占多大的比重呢?

倪健:通常我们进入一个领域是需要时间的,并不是说你缺乏领域知识就不能做这件事情,你可能还会做得很好,所以我认为领域知识占的比重可能在30%以下,这是我自己的判断。

提问:但是我听说另一个说法,领域知识比需求更重要。因为所有的需求都来源于领域,领域的东西是不会变的,而需求是不断变化的,如果从领域的范围来做更符合客户的需求,你有怎样的评论呢?

倪健:我以前在单位碰到过,很多人跟你讲领域知识的时候一大套,可以滔滔不绝讲一天两天都可以,但是有用吗?没有用。关键不是领域知识,是你组织领域知识的方法。你要把这个领域知识表述出来,这就是我们软件公司和客户的需求,否则客户的领域知识比你大,为什么他不做需求开发呢?他的领域知识最多,肯定比你好。关键是你怎么组织这个领域知识,这点非常重要。你给我讲两三天,我觉得没有任何意义,我也不需要听,这都是杂乱的,没有经过自己的组织。这样还不如直接跟客户交流。

提问:最后有一个问题,你不同意团队决策,其实在我感觉对于一个小系统可以是个人决策,这没问题,比如刚才的打印系统,但是设计一套大系统的电子商务网站不可能实现的。

倪健:你可以有总的决策师,下面分派给其它的决策师,您可以过关,也可以检查它,听取大多数人的意见,和少数人商量,自己拿决策,只有这样才是最高效的。但是前提你要有成功的故事。对于投资者和经营者来说他需要放心把这件事情交给某个人或者是自组织的团队,交给一个人决策也不是我说的,是软件构架实践的书里面说的。为什么呢?因为这可以减少很多,他决策不是决策到任何的细节,但是可以有分派的机制。你可以解决这个,我信任你,你可以在这个范围内做这些事情,但是最终要我来决策这个事情要不要做,或者是我认为应该把关的地方。我讲的是这个意思。

提问:我们这样的架构师可能要设计很多情况,我不可能都了解,必须交给一个合适的人替代我来决策?

倪健:对,你可以委派。他需要有成功的故事,这是一个比较偷巧的办法,这也是敏捷方法里面写的。他问到一个人:“那家公司的交付记录很良好,你有什么秘诀?”他说:“没有什么秘诀,也没有什么方法论,就是找有成功记录的人,他以前做过什么事情,成功了,我把它拿过来,它可以帮我成功,我信任他。”

刘江:倪老师的意思是说最后需要有一个拍板的人。苹果为什么很成功,因为有一个很牛的拍板的人。Java有个委员会设计,他是典型的,因为是委员会在设计,所以实际可以看到是这样的。当然这也取决于老大的能力是否足够强,是否可以为我所用,这是一个问题。

提问:能否谈一下您在设计过程中对设计模式的应用?

倪健:设计模式我用到一些,但是用得不多。我曾经去面试的时候还被人说,这个怎么不知道。但是很多东西我只是说自己,我有这种想法,当我需要的时候我去看两个小时、半天或者最多一天、两天、三天,这个东西就可以用到。另外一个说法,我需要事先有一些设计模式在里面才能设计出一些东西,还是我设计然后再去用一些相关的设计模式,后来把它加上去?比如前面有一个初步的想象,后面一定要去为了凑这个设计模式把设计模式加进去,有两种说法。我认为顺其自然。你需要的时候自然会想到去用设计模式,我们在前面已经用到很多设计模式,这个模板、代理都用到了,工厂方法都有。

提问:你认为软件架构设计第一步要想到什么?你刚才说了,我们的领域知识很重要,需求很重要,但是软件架构师首先想到的是什么呢?

倪健:这个很难讲,我可以讲最开始想到的一些事情。比如我要做一个架构设计,首先要有一些输入,会拿到一些文档。凑巧我正在看一本小说或者做什么东西看到一个流程,我可能就把这个流程用上去。当时脑子第一反应前面的流程有点像,我可以把这些事情隐喻在里面,针对它去抽象他的公共特征,就是说公众模式是什么样的。像最开始的直方图,我想到的可能是抽象的,有个东西进来,要怎样格式化转换一下,然后怎样去装配一下、处理一下。但是你可能换一个场景,比如说去哪个超市买东西,第一个到货架上取一下,这都可以。

提问:我们软件架构设计出来基本和业务关系不大,但是作为软件架构师对于业务的关注显得很重要,你怎么理解这种现象?

倪健:可能我的想法有点不同,我认为业务很重要,但也没有重要到一定要知道业务才能做这件事情。我可以拿一些通用的需求,提炼一个公共模式。因为客户的工作模式相似,可以套用在上面。我前面介绍的框架是03年设计的,那个时候对业务也不知道,但是实际就在使用。

提问:我们软件架构设计出来以后和我们的需求看起来关系不大,但是做软件架构设计的时候我们又非常关注一些相关的需求,可能是主要的或者是次要的需求,只要你想了解都会想关注。为什么会出现这种现象呢?

倪健:前面提到有个大概的商业模式背景的了解,业务也要提炼出工作模式,如果我不懂,也可以通过内容填充检验它。比如刚才设计了这样的框架,有这样的规则和操作,我在实际的使用中这个是否可以做,将来有多出来的工作模式,我是否可以扩展,加进去这个模式也可以解决它就可以了。填充的是领域知识,你要从领域知识发现公众模式,这是架构师需要做的。

上海博科资讯技术支持中心经理周志军演讲实录

上海博科资讯技术支持中心经理周志军

 

周志军:刚才倪健老师给我们说了很多设计上的原则、方法、理念和概念。我只说一下实例探讨,是我们做过的管理软件的架构探讨,我们在研发过程中的技术细节或者是结构经验的细节分享和讨论。

首先介绍一下标题里用户自主的概念是什么,我相信大家都应该碰到过这样的问题,我们怎么保证定制能力。对于管理软件的客户,大家做项目都知道,他们有很多需求,这很正常,因为在互联网时代有很多新的业务模式。所有企业虽然都是做物流、运输业务,但是他们有各种各样的思路,比如申通就是基于淘宝的快件运输非常准确和及时,如果帮别人运工业材料完全不一样,所以必须有差异化企业才能生存。所以你要适应企业的要求,企业同样是ERP、CRM,但是有这些需求,对我们这些不给力了,怎么办呢?在架构上关键要解决重用和定制的矛盾。客户说帮我改一下,否则用不了,因此架构设计中重点要解决重用和定制。

第一,客户有这个要求,重点在于这个客户有差异化的产品和服务,否则和市场是一样的,要么价格弄得很低,要么没有竞争力。第二,他要做的事情可能和历史有关,有些客户以前和铁路在一起做,他的做法和以前公路运输完全不一样。还有一个就是市场在变化,以前我做一个业务很赚钱,过几年不赚钱了,怎么办呢?我只有换掉。最终还有一个,企业并不需要在你上软件的时候改他的业务模式,因为对他来说有两个问题:一个是风险,你改了他的方法有未知的风险。二是没有人担这个风险。

对于我们开发者来说有几个问题,我想大家也经常碰到。第一就是我到底把资源放在软件升级还是项目需求上。第二就是版本,有的时候每个客户一个版本,很多客户里面的功能你抽不出来,没有办法放到里面去,甚至A客户和B客户是矛盾的。对开发软件人员来说,所谓的定制模式也会带来这样的问题。

一般项目定制可以这样,一个是我做一个可定制开发的框架,这个很多,还有一个就是我做一个配置化的平台,不需要代码做相关的项目开发,所以我们提了一个全配置化的概念。这就是我们现在的框架并不能百分之百达到目标,但是这个框架一直往这个目标去努力。

第一,不使用代码,没有编译、发布和部署的过程。第二,通过对业务模型的配置及时调整业务。第三,使用脚本作为辅助手段,提供进一步的灵活性。

这个介绍就先过去了,我想大家比较关注于技术方面的东西。这个架构一看就是市场方面的图,大家也画过总架构,不仔细说了。

我们看一下这个平台的核心概念,这一点可以认为是我们设计之初的这个平台的业务需求,为什么做这件事情,这件事情是怎样做到的。看了这个以后,对后面的设计可能会容易理解,所以我要仔细说一下。

首先对所谓的业务定义用户,大家如果做过企业软件,比如有些企业的IT会做孵化表,很多财务人员会把系统导出来,自己分析来分析去,这种人可以认为是关键使用或者是比较资深的人员。我们会给这样的人提供工具,一个图形化的界面去描述业务,而不是代码。这项业务可能是一套语言或者怎样,配置文件表达出来,比如说一个表单可能会定义表单的名字叫什么,对应哪张表,有哪些字段,这些字段各属于哪些类型。对系统来说,我们在运行的时候会加载这个内容,这个东西可能有很多规则,有很多描述和定义,系统加载以后就产生一个应用软件,最后是普通的用户操作这个软件。这是我们这个框架的核心概念,所有的设计都是为了实现这个目标而去做的。

我们大概分三块去讨论,一块就是架构示图,几个点,第一个点就是我从架构层面考虑弹性和效率。弹性就是可应用配置,效率就是开发的效率,怎么去平衡。第二,怎么保证这是够用的。不是客户的A需求马上帮你配置出来,B需求我做不到,要回去找开发人员,或者开发人员也找不到,所以我们要看功能的可扩展性是怎样实现的。第三是易用性和层次。这非常重要,其实大家可以看,首先不要让用这个框架的人感觉很麻烦,这个框架肯定要实现易用性,框架是面对关键用户,不是程序员。再者就是层次,大家刚才谈到要不要做过度设计,一开始就设计全还是怎样。一个架构如果大一点是不可能一开始就全部设计出来,所以在设计的时候你要遇到很多层次,在这些层次上可以在不同的级别上去扩展。

第二块就是一些技术细节,因为大家也是一些开发人员,所以我会把框架用到的东西给大家看。第一,是框架用什么方式来实现这种可扩展性,我们可以以一个报表的结构为例。第二,我们是怎样使用MAP,这是对扩展很有帮助的。第三,我们框架用了很多经验,怎么去灵活使用,用一种什么样的概念把公式和业务结合起来。第四,是统一资源访问,我们针对统一资源访问的概念做了什么东西。最后,提一下技术框架之外的东西,很多东西不仅是管理,还有理念上的,有一些技术之外的东西,会稍微提一下。

刚才我们说到弹性和效率,决策上有这么几种。第一种,是由业务员出具的东西,其实是业务的模式。这个原数据其实是很重要的设计,像刚才有人问到要不要知道领域知识,领域知识是必须的。不是说领域知识拿过来就可以用,领域知识一定要经过你的抽象放到框架里,否则就不是框架。所以大家可以看到这个领域知识我们有这么几块,当然可能不够,我们可能再加。比如数据模型,很多时候所谓的领域设计最主要就是数据模型,比如保险业务涉及哪些基础的业务对象、哪些接触过程中的表单对象以及报表中的KPI。第二种,是业务键模型,其实就是界面了。第三种是业务对象的状态模型,比如单据有审批,审批了有状态表示。在这一块我们首先要实现弹性的措施。其次就是我们也决策,我们舍弃了框架,使用一种通用的类型,这和弹性非常相关。我们相信这个系统不要经过开发、编译、部署,直接可以看到改过的结果,所以我们会关注通用性。这个很简单,好处在于我可以把它序列化到处去传,也可以编辑成各种各样的格式,在跨平台之间也不会有太多的障碍。

第二,我们会关注Java公式的结合,后面会有专门的思路来谈。

最后,我们在设计框架的时候专门考虑开发者的模式,这个有点像ID的考虑,要为开发人员提供很多方便的东西。举个例子,我在开发模式原数据可以动态加载,这个是需要性能成本的,所以开发模式可以做这个事情,产品模式不可以做这个事情。你也可以用它做一些Java程序,调整时不需要重启服务器,所有的变化可以更新到系统里面去,这个话题就比较长了,今天不会详细说。

第一个刚才看到的数据模型,这是我们第一篇数据模型,大家可以看这其实是配置文件,为我们提供了一个文件,让它可以管理和修改这个东西。我们认为一个人如果手工改这些文件是很大的问题,所以我们提供这个界面,很简单,这个很明显是明细表,你也可以做更复杂的,这是我们的业务模型。这个就是界面模型,其实界面模型没有什么特别的,感觉上和设计系统很接近,但是有一些很重要的东西,就是他把所有的东西都抽象在这块地方。比如客户只要说我是来自于客户表的字典,这样的话我不要做任何操作,这个页面的对象就能够提供很多的功能,比如可以点对话框查询客户,这是界面模型上的实现。

这就是我们谈到的业务对象的状态模型,大家可以看,这张单据我们认为有几个状态呢?首先有一个已输入状态,已确认状态和已关闭状态,我们把这些状态和业务操作结合起来,这样把业务的逻辑用比较便于理解的方式转移出来。

这是为了适合我们的弹性在原数据上做的一些设计,只不过现在给大家看的是在一个基于设计成果做的开发工具上做的。刚才提到第二个架构示图是功能的完整和可扩展,弹性和效率也有一个关系的脚本,后面可以提一下。

功能的完整和可扩展,其实是相关的,因为从设计角度不可能一开始做到完整的功能。你希望的完整只有两个措施,一个是系统可扩展,不要加一个功能核心代码就要改一行,这样到时候维护人员都要累死了。第二就是你的积累,你要看积累的方式在可扩展的核心上实现功能的完整性。

我们看一下,这其实还是原数据,我们看到界面和逻辑示图,这个是代表了领域的语言,我们刚才把我们的配置认为是这样的语言。通过语言,我们把我们的业务过程变成了所谓的模型、界面和业务逻辑,其实后面有一张图会有说明,到时候再详细来说。最后的业务逻辑可以扩展为服务,可以这样来用。

第二,基于业务员数据可以进行服务信息,因为我在字段上选择了名称,大部分情况下只要把字段和界面关联,如果过几天变了不需要到处改,只需要改一个地方就可以了。还有一个可扩展的组件库,必须实现可扩展的组件库,否则就无法实现可扩展。

我们一个一个看,这个视图里面有各种各样的概念,我们抽象一下用户界面和处理代码之间其实有一份东西,很简单,可以先定义好业务数据,可能是一张表单,也可能是含有其它结构的表单,然后我可以很快地基于业务数据实现用户界面,对你来说很多时候只要加个字段就可以了,我们希望界面支持这种修改,自动放在最后一行,当然你可以修改它。再看业务数据,我们用自己的方式把公式、脚本这些东西通过一个处理逻辑把它关联起来,后面可以看到处理逻辑的例子,处理的结果就是更新的业务数据,同时更新了页面,这个逻辑是我们系统在处理一个用户界面和后台逻辑管理上的思路。

大家可以看到这个例子,首先是业务逻辑,是报表查询,首先查询一下所有定单,定单里肯定有业务日期,一般叫出货日期,然后要统计每个月的订单金额的分布,不同的客户,不同的订单,不同客户每个月的金额分布,所以我会做一个映射的过程。你算到月份以后就可以做汇总。

这是业务模式,在业务细节上这个地方有一个规则的设计,是对所谓原数据的操作,我加了一个订单月份,订单查出来有一个数据,通过这个数据对它进行操作。这个操作怎么实现呢?我通过一段脚本,我只是用一个时间处理类把当前的时间对象变成一个YMD的格式,这样就到了月份。这就是一个简单的例子,我怎么实现业务逻辑脚本和业务员数据之间的关联。

刚才说到可扩展性还提到一点,我怎么实现一个可扩展的系统结构,我就以这个图简单说一下。我们认为这个系统所有的子系统,你的扩展,你希望加的功能最好以一种标准的方式加进去,而不是需要改一些东西。这个架构是系统组件,我们做什么事呢?会做一张页面,你可以观察系统什么时候做连接,什么时候做泄露,在哪个代码点上泄露的。首先,这个程序肯定要Java代码,我们放在这个地方。第二,我们会把程序挂接到系统里面去,所以放一个配置文件,一个挂接点,这个是WAP程序,需要一个WAP入口,要定一个URL,定好之后还有一些资源,比如我的GS文件、CSS等等,我就可以放在资源里面去。这个东西其实是标准的项目,经过它,基本上你用PP打开就可以了,编辑完以后打成一个架包,系统就会搜索。如果有这样的文件就读取你的内容是否进行挂靠。我的核心技术不用变化,甚至代码也不用发布,某个客户需要这个功能,产品开发人员只要打包出来,发给客户,客户投进来就可以实现扩展性的功能。为什么强调这一点呢?因为完整是不可分割的,如果没有扩展性,无法做到完整的东西。全配置的框架我相信很多人思考过,尝试过,如果没有好的框架设计你要做到功能完整就很麻烦了。

第三个就是所谓的易用性和层次。我们认为越靠近所谓的商务层面应该越简单,程序员就在做复杂的事情,但不是一遍一遍重复做复杂的事情,而是把复习的事情抽象化以后以很巧地方法实现,只要做一次。下面一层一层的人员,比如有个框架开发的团队把某个需求作为组件实现了,产品团队不需要做这个东西,肯定产品有N个需求,他可以在产品里把它组合起来。到了实施顾问那里就更简单了,也不需要关注我后面这个细节怎么做,他把已经定义好的保存、修改、删除再关联起来变成典型的业务形式,这就变成了分层次的配置。重点是说越高层的配置越简单,这个其实也有很多代码,到你修改配置文件和接口的时候已经复杂掉了,看到的只是接口和定义。

然后是多个层次的合并,这个层次的概念不一样,大家可以想象一下,我系统有个总的CSS文件,每个文件定一个标签范围再定一个CSS,在我们这里也一样。首先我们考虑框架层面的开发人员他应该做哪些工作。比如说用户管理可能是这样做的,但是出货订单不应该做。第二个我们说产品层次的人做哪些事情,就是入库单、出库单。最后是实际给客户的时候,项目人员需要做什么事情,我要换一个出货单。后面也进行说明。

这个和刚才一样,我们通过易用性可以实现稳定的核心,稳定的核心在于不需要很多人做核心开发,可能只是投入一些最聪明或者最有想法的人做核心开发就可以了。范围比较小,容易控制质量,核心的话不会每天升级一些事情,不会A客户的要求加进去以后造成了B客户又出错了,那是不可以的。所以稳定的核心减少了核心需求,这是第一个在层次上可以实现的功能。第二,可扩展模块一方面避免了核心的臃肿,核心臃肿是非常可怕的事情。架构设计都知道,可能一个很小的动作到时候影响一大堆项目。

第二叫功能抉择,如果把所有的功能都放进来,上一个客户和下一个客户的需求不一样,下一个客户又需要上一个客户的需求,某些功能不需要放到产品里。这是很讨厌的过程。你现在不放,过几年发现很多客户都需要,所以通过这个功能来避免。

我们来看刚才层次的例子。举例来看,界面上的数据显示都有格式要求,我在核心层会定义数据怎么显示,比如日期类型就这样显示,数值就是两个小数点,字典就用这个框显示,这是默认的东西,也不用改,默认就可以享用这些功能。到了某个产品,有人用的框架做了某个产品,日期类型感觉不用变,就这样了,他什么都不用做,我们天然继承这种日期显示方式。到产品感觉很多,你用框的话肯定是很不友好的,所以要求换成一个可搜索的对话框,输入第一个字母回车就可以选择产品。第三是数值,财务说要4个,所以在某个单据上把这些定好,当然其它的可以不变。到了某一个项目里,人家说喜欢这样连续显示,就换成这样。我们面向业务就是这一层,在这一层的时候要改动很小,因为涉及到的东西都在每一层介绍下来,大概是这样的情况。

第二个例子也简单,新的单据会有修改、保存、取消,持续里面有个作废功能,加个作废,其它的东西都继承了框架里面的东西,不需要做太多的调整。某一天框架加了发送邮件的功能,这个产品只要框架申请上去,也不需要再配个发送邮件的功能。这是我们多层次合并的思路。

还有一个多层次的概念,是模块化和层次的实例。这个有一定的订单编辑的界面,我肯定尽量跟着大部分的业务来做,不同的行业会不一样,所以会在中间加一个行业模块。这也有一个订单,但我会定一个新的。可能有的行业很简单,有的行业很复杂,对于我的模板来说,编辑新的界面已经覆盖了上面的编辑界面,它也是一个架包,其它地方不用改,连订单的查询列表都不用调整,这是编辑的时候被更上一层的人替换掉了。到了某个项目,这个模板界面也不够用了,可能会改一下,这也是基于以上的替换原则,这个项目就和其它的产品一样了。

可以说一下原理,涉及到刚才说的统一标记化的概念,包括界面、脚本、公式都是统一的,界面、脚本都是资源,我们有一个模块加载的顺序,比如加载的优先级。项目里的东西是优先级最高的,然后是产品等等,在这种情况下我的订单编辑是用URL编辑的资源,只要你这个项目有了,后面的东西就被我屏蔽掉了,通过这种方法来实现模块化应用的实例。

这个就是我们技术的三个视角,我们可以回去看一下,一个是弹性和效率的数据,一个是功能扩展性和完整性,还有易用性和层次的树视角,这是比较重视的方面。

技术细节和架构没有什么关系,只是实现架构的时候有很多东西,可能有设计模式,或者可能有一些技术能够方便我们实现这样的架构。这个报表是Excel,对客户来说最方便是用Excel来编辑东西。第一个设计,因为有Excl,我就借助原本的功能放一些原数据信息。现在这个代表分组,是所谓客户编码的分组,这个代表产品号需要用条码打印出来,这个地方有一个低级和供给,这个扩展是怎么做的呢?是定了语法,首先你是哪种扩展,比如说页码,你可以验参数,这个地方是个模板,这里面的变量代表当前页号,这是之前的页号,你可以给第多少页,就是这样的概念。

我们怎么实现这个报表的框架结构呢?下面有三个,我每个报表的元素怎么去构造出来。第二个是改一些格式。比如你填了一个黄的背景,可能有日期的格式,大家知道Excel也可以设格式的。我们会用一个这样的方式去调整这块所谓的该显示或者该有的属性,这样的好处在于以后加一个属性对我来说很多系统不会做这样的变化。第三个是预处理,现在有个页码功能,明天需要有一个时间的功能,我就用页码做一些预处理,这样报表的这个元素就会这样去显示,至于怎样去预处理其实这个各显神通,只要你对报表了解都可以插入自己想要的东西。

这是一个简单的说法,我们通常使用的模式叫询问的模式。所谓询问的概念就是说我是为了实现什么呢?比如说我生成一个报表元素,这个时候有一个问题,一旦你的项目要改,做了新的,这个时候我怎么保证项目可以替换我系统中原有的呢?有两种方法,一个是实现名称,因为是个接口,第一种方式是做个映射,把它初始化出来,把这个元素建起来了。还有一个去问到底谁可以处理,反正这个列表可以在系统里无限增加。你去问,到底谁可以处理,第一个可以回答我处理的人抢到这里,后面的人没有希望去处理。这个可以采用很多东西,可能这种不能实现,可以通过更多的模式来处理,后面也是一样的,我们更多是用询问的方式。像刚才说的,有所谓开发模式和非开发模式的区别,开发模式是因为你在变,系统里面有10个,你去变,每次统计报表就询问十次。但是产品模式下可以缓存,你交付系统以后这个系统不会经常变,就是第一次查出来,以后不会变了,这是效率和完整性的折中。

第二个,服务器端JS是非常有效的,大家转移的时候没有太多的障碍,而且编辑语言、流程性什么都有,所以说用起来很方便。我们介绍的引擎叫Rhino。模型上有几个概念,一个是多层的上下文,可以这样理解,首先系统可以有上下文,大不了就是变量、方向和方法。我们系统可以这样,Root—Module—Instance,Root就是每个模块都可以用,我可以定一下数据访问的东西,或者是订单的,可以定一些定单常用的方法,你就不需要写了。第三就是具体订单产生的时候,还可以有一个上下文,可以调定单对象的方法。

宿主模型,如果Java很熟,在服务端也可以搞一个宿主模型,你可以以这个订单进行处理,进行保存或者取消都可以。这个所谓的宿主当前有很多种,有时候你要处理很多记录,我给你一个记录,这个迭代过程系统帮你做掉。后面还有性能调试,其实很简单,在我们的引擎里面有一个上级的上下文,其实客户端的Java也是这样的逻辑,可以指定一个原级,可以套用很多层实现这个东西。

这是一个报表的脚本例子,当然这是我们试验型的报表,比较简单。这个是我们给报表上下文做的东西,你可以设报表参数,你也可以读报各种信息,甚至可以调整报表的属性,比如说测一下字号或者什么东西,这就是宿主模型的使用例子。宿主模型很简单,就是把Java对象取个名字,这个时候就是变量名。

预编辑其实没什么技术含量,很简单,只是你执行了这个脚本以后我说的上下文都在里面,你只是用这个来套,而不是原代码。

接下来介绍一下调试器,其实这是很纠结的过程,因为刚才说要尽量便于配置,为什么要有调试器呢?用的时候还是控制不好,脚本比较复杂,这个是基于helma的项目,我们并不希望用调试器,否则框架目标就失败了,只是他有这种需求。

刚才说的第二点就是公司的应用,这里举个对公司上下文绑定的例子。你可以想,现在查出的数据有产品的价格和数量,现在我要算一个税后金额7%的增值税,对每一行数据,查出100个产品,每个产品建一个增值税的列,我们怎么做的呢?其实说白了也很简单,首先要解析,然后变成几种东西,价格我称之为变量,这个是操作符,0.17是个常量,基本是这样的思路,当我解析完有一个绑定的过程,这个过程绑定上去,很简单,我只是把这个在公式里换成这样的东西,所以你绑定以后就算出来了。这是我们对公司处理的思路。

统一资源访问简单介绍一下,这些协议都是公共的资源协议,我们自己也可以定一下。这个有点参考,比如说resource代表你架包里面的子,service代表你的资源,这个时候定一个服务很简单,不管在哪里都可以拿到。再往下是资源重定向的概念,就是说和刚才的这个例子看一下,应该有一点点接近,但是我们换一个思路。行业模块订单编辑现在就是编辑1,只是一个概念。

基本上技术这块就讲完了,最后提一下这个架构的实现在技术之外的部分。这个其实是非常重要的,为什么有些人成功,有些人不能成功呢?完整性你可以配置,但是只有50%、80%的功能可配置就大大降低,所以完整性不是简单可以达到,而是有十年的开发历程,也不能所有的业务都可以包括,如果说保险我还要考虑一下。

第二是文档。其实文档在开发团队中一直有两种处理方式,第一种是Javadoc,组件越来越多没办法找文档,Javadoc是最简单的,最后问到程序员就可以找到,不要你改了而我没改,最终没有办法定位。我们都给一份Javadoc,看一下怎么配就配了,不需要专门弄一个文档出来。第二就是文档信息,其实我们做得不够好,在刚才的界面上也不够多,客户肯定要拿一份说明书,典型的是数据库报告,如果多了更好,我们可以在原数据上加说明信息,可以生成这样整体的文档报告,也是我们需要后期加强的东西。

这就是我们实现过的界面,再看一个复杂点的,会有图之类的在里面。这个界面就比较复杂,有一个图表,这个地方有流程表,很复杂,运行这些模块相当地慢。

大概这样差不多了,我就先说到这里。

刘江:提问环节。

提问:我想简单知道一下你们现在有多少个模块,项目有多大的规模?

周志军:我不是很清楚,因为我很少跑到销售一线,但肯定非常多,像大型的企业客户几百个是有的,但是不确定,不做可信度的保证。你说项目的情况,我们看一下后面几个项目的简介,比如说这个项目,有一些项目只有几百万级的,这个企业大家可以想出来,这是一个经销商管理系统DMS的情况,我们很快做出来。这个项目有个好处,客户系统里面有部分财务的东西不放心让我们做,但是他们有个IT,他们会自己把财务做出来,所以财务我们没有权利做,他们自己做一套,可能也是因为他们比较容易上手。

提问:您主要做哪个模块,我们知道无论是SAP还是用友,你主要关注哪个模块呢?你们公司。

周志军:财务、ERP加供应链管理,你可以到我们网站看一下。

提问:我想请问一下,您从系统的架构到框架到技术细节都讲得比较整体。我有一个问题,您公司在做架构的时候有没有一个成型的架构,就是做完几个架构以后同一个模式会在这个结构上修改,后面就可以升级为公司的用户架构。

周志军:我先说一下架构历史,最早是从ERP过来,所以现在还有很多ERP的痕迹。你要说供应链是有差别的,这几年调整过来的,最早是写代码的,这个代码也不是一下子想出来的,是积累出来的。我们的逻辑是先出标准产品,也是做过一段时间以后才有标准产品。我们的做法比较简单,有了框架以后做法是这样的,首先这个行业是没有看过的,至少有一个可配置的框架做底,然后你就开始做,等你做了就会有行业的第一个例子。大家也是这样的,可能有些人写代码,有些是配置,过程当中比较痛苦,这个行业有自己特有的东西,这个时候我的框架还不能支持。当我在这个行业做了一段时间以后,比如现在在物流行业或者是ERP的行业里面也做了蛮久了,做这个就比较简单了,我们要做一个标准的产品。标准产品像刚才说的集合,就是集合的几个层次,我这个层次上所谓产品的概念,我可以做个产品,这个产品是面向行业,但是有了这个产品以后,产品的意义是什么呢?不是在于没有产品就不能做这个东西,而是有了产品之后再做类似的系统可能就不需要开发人员参加。可能比较关注懂业务的,类似于顾问,就是行业顾问这样的人和客户打交道,就是说他不需要太关心代码,这是我们有产品以后的好处。

至于模块你可以做一些行业模块,你做的行业比较多以后,可以把模块方式提取出来,或者以后可以发表一下。

提问:刚才倪健老师在讲课的时候大家有一个问题不统一,行业经验、领域知识在软件的架构之中所占的比重,周老师你们做了很多的框架,也接触了很多的行业,我想以你的经验来看这个困局,领域知识到底占多大的比重呢?

周志军:我还是同意倪健老师的说法,并不需要有很深的领域知识,有一个抽取的过程。有两种人,比如我看很多需求,基本上根据我以前其它方面的经验。其实经验非常重要。倪健老师说第一个看到什么,有没有做过,你就多看框架的代码,这样的话很容易知道别人碰到这个问题一般怎么做,慢慢会形成你的模式。这个模式我们用的很多,你碰到这个问题感觉可以解决,就是这样做的。

领域知识本身如果真的做核心代码,我觉得可能会需要一部分,但是这部分很多时候并不是你需要了解,可能是前面反馈给你的。比如我是客户的相关方,我最初设计认为相关方就可以搞定,选一个客户,但是过段时间又找你了,一万个客户要看到什么时候?最主要是基础比较好,不会影响别人,这一块比较重要。

提问:你介绍了一个非常通用的可以扩展、可以配置的框架,一般来说越是这种通用的框架,效率和性能也低,你这个表越是通用,符合各种需求,这个表的结构越是复杂,效率也就越低,我比较好奇你们如何做到优化,是不是用到特殊的表格设计、特殊的缓存、或者是非关联性的数据库?

周志军:这个问题很好,尤其是这种框架一直会面临着一个疑问,你的效率是怎样的。确实是这样,某些地方是可能存在一些性能的问题,但是其实这个性能问题像我们设计时说的,你不是一开始非要考虑性能,很多时候性能等发现再解决。所以我们在设计的时候是考虑了一些性能的问题,比较常见的方式像我刚才说的,我有一个所谓的开发模式和支持产品运行的模式。举个例子,我在开发的模式下会非常关注弹性,也就是说怎样开发这块,怎样调整可以产生我们。到运行模式下也会考虑到效率,一个是缓存,缓存确实是提高手段,第二就是预微的操作,当原数据加载以后这个过程的效率就可控了。第三就是脚本和公式第一次运行是文本方式,是编辑的过程,第二次运行以后也会用缓存的方式,但是不代表所有的情况。我放一张报表的脚本,这个时候我们认为效率并不是特别重要,因为和你的数据相比其实是百分比很小的,但是如果我在一个替代过程中一直调脚本,我们会一开始做优化,缓存以后的东西,就是这样的概念。再更多的细节,有些是数据库的设计,那个其实和其它的管理软件都是一样的,不知道你是否还有什么问题?

提问:我想问一下,因为做系统来讲可以从几个方面来理解架构,一个是业务层面,就是针对我们的业务人员,一些领域专家。还有一个层面就是用户体验架构,这一步可能更多涉及用户的操作人员,还有系统的开发人员。作为架构师我们能够更好地把这三个层面的问题做一个平衡,我想问的问题就是如何能够更好去平衡这三个方面的问题呢?

周志军:其实这个平衡很多时候还是个人的经验和感觉。感觉还是比较重要的,像不要过度设计,有对也有不对,其实有多种可能。不知道倪健老师有什么想法,我个人很难提出一些针对性的可行建议。因为做框架的时候我们也碰到过弯路,最早的时候我们公司就是从头到尾把结果算出来,结果没办法做这个东西卖,这样的操作做不出来。其实这个操作在最早的实现过程中是很丑的,上面加了很多补丁就成了这样的东西,具体到细节上的操作是很有可能不是很优化的。但是像层次一样,我可以先在上面把一个大层次构造好,这样的话我考虑到每个结点的灵活性和可替换性也是涉及几个原则,我要保证这个方法是可替换的,这个类可以被那个种类替换,我可以不断优化它。这个架构不可能一开始就做出来,走了很多的弯路,前提是要有优化的过程把这个代码做得越来越好,而且你以前做的决策以后可能会觉得不够好,这是很常见的情况。前提是你可以在框架呈现一点一点调整,而且保证结构的完整性,不可能做出来就是完美的。谢谢!

 

 





    网友评论(共0条评论)..
    TUP第七期架构师沙龙现场演讲实录

    更多热门活动

      更多热门招聘职位