工作流系统的设计

workflow

几年前曾经写过一点点对于缓存框架设计的体会,这大半年和工作流系统打交道颇为丰富,因此想总结一点关于工作流系统的设计。

首先,明确工作流(workflow)系统的定义。维基百科上有极其简单的介绍。我记得以前在文章里面说过,作为大公司里面的小team,为了做一些有趣的东西,从而更好的招人,通常有几个众人皆知的突破口:比如一个更符合业务需求的storage,再比如一个自定义的工作流系统。在Amazon内部,我接触过好多个workflow,而且大多以Amazon SWF为原型(当时学习的时候还写了一点体会,link 1link 2),于是宏观上看,60%的东西是一样的,大同小异;但是也有很多重

[……]阅读全文

追求纯粹

pure

偶然想到的这个话题,工程师做工程是一方面,而作为单纯的程序员,总是充满对于纯粹的追求。

最近又负责了一个使用Angular的项目,我们知道最近Angular很火,其中一个重要原因就是它给前端开发带来的变革,第一次发现可以让以前如此恼人的变量绑定消失掉。以往变量绑定的语句放在附属于页面的一个js片段(文件)里面,颇有些无奈的意思,如果把它视为展现层面的东西,显得很不直观(声明式编程才是最直观的方式),而且让这一层变得啰嗦;而如果把它视为下面一层的东西,这又让逻辑代码变得不纯粹——凭什么要让逻辑代码去了解哪个dom叫什么id?于是Angular来了,引入了$Scope这代表上下文的东西,变量绑定

[……]阅读全文

重新发明轮子

wheels

“不要重新发明轮子”是总是可以听到的话,在评判一个设计的时候,总是听到这样的话。但是凡是不绝对,而对于这句话来说,很多情况下,都是错误的。我甚至都不能说出“大多数情况下不要重新发明轮子”这样的话,因为具体问题,实在没法用大多数还是少部分来概括。重用轮子有什么好处?省代码;轮子已经经过千锤百炼,质量有保障;轮子功能在逐步更新中,可以看到未来的获益。但是,也有一些情况让我无法重用轮子。

第一种情况,我只需要一点沙土,我不需要整座大山。

比如,我只需要一个StringUtil.isEmpty这样的方法,判断字符串是否为空串或者null,如果引入

[……]阅读全文

程序的库设计

think 最近在Stack Exchange上面看到一个帖子,是问程序库设计的指导原则的,“What guidelines should I follow while designing a library?”,有趣的是,很多人都在谈论面向设计,各路API设计,还有程序语言设计,唯独搜索“程序库设计”,无论中文还是英文,Google还是百度都找不到太多内容。但是我想,没有程序员会否认库设计的重要性吧,我想在这里结合这个帖子谈谈我的想法。

在这个帖子里面,votes最高的回答,提到了这样几类tips,我在下面简要叙述一下,其中基础的部分包括:

  • Pin Map,明确你期望库主要用来做什么,但不要把它定得

[……]阅读全文

对几个软件开发传统观点的质疑和反驳

why 下面这些观点都是程序员在教科书上、在编码规范里、在正统的软件工程流程里流传开来的,帮助了许多人在程序员启蒙期间养成了良好的习惯、原则。对许多人(包括曾经的我)来说,似乎是理所当然的。但是随着阅历的增长,视角在变化、看法也在变化,曾经的好恶现在都可能大翻身了。

为代码写足够的注释,让代码易于理解

“所有程序员都会写自己看得懂的代码,但只有优秀的程序员才写大家看得懂的代码。”这话没错,但是——

  1. 什么才是“大家看得懂”的定义?我有必要让我的C++代码对于一个月前才明白指针和引用区别的初学者简单易懂么?
  2. 更重要的

[……]阅读全文

对象转换的问题

image 有句话叫做“计算机科学领域任何问题,都可以间接的通过添加一个中间层来解决”,但是唯一解决不了的问题,是层次本身过多的问题。每一层内都会维护自己在乎的数据对象模型。层与层之间数据的传递,就不可避免地遇到对象类型转换的问题。

这个话题也和最近的项目有关。我们在重构一个老旧的系统,所做的第一件事情,就是要把数据访问层从原有系统中剥离出来,我们精心设计了这一层的模型和结构,但是要让原有系统平缓地从原有数据访问方式上移植到新的数据访问层上,就涉及到上层(Service)的原有数据对象和数据访问层(DAS)之间的数据传递,而二者模型并不相同,而且原有Service的模型并不纯粹,既不是充血模型,mode

[……]阅读全文

DAO的演进

1 这个思考源于最近项目中对DAO的使用和讨论。数据访问对象,在贫血模型下,要怎样去设计,框架需要完成什么,后续的开发人员需要关注什么,设计的时候到底需要把握怎样的粒度?

最早做项目的时候,是老老实实给每个必要的模型增加DAO接口和实现类的:

public interface IUserDAO{
    public long add(User user);
    public void delete(User user);
    public int count(String condition);
    ... ...
}
public class UserDAOImp

[……]阅读全文

设计之美

到处都在谈论UI的美感,仿佛“美”在软件工程中的定义就要落到界面上面。实际美的存在是广义的,包括架构设计,包括代码建设,包括接口定义,不妨在更多的场合引入对美的评审。软件本身就是一种艺术品,而程序员,应当是被赋予创造力的艺术工作者。

 

仅看这两张图,你觉得哪一张会更美一些?

我相信大多数人会选择第一张,因为后面那张图显得头重脚轻,事实上,后者也确实是一个短命的版本,只存活了不到半年的时间。这两张图,正出自淘宝发展的一个阶段(来自淘宝赵超的博客)。而且,进一步观察发现,对于许多设计图来说,狭窄的汇聚点往往成为性能的瓶颈。

另一个设计上典型的丑陋是混乱,如下面的设计图:

我不相信看到

[……]阅读全文

过度工程

prj 过度工程,最初我知道这个词是在Rod Johnson的《J2EE Development without EJB》,随着阅历地增长,渐渐发现书中熟悉的场景也在身边再现了。

 

敏捷、还有设计模式,给一个团队带来了什么?

我之所以把这两个词放在一起讲,是因为我要说一件显而易见的事情,可是这样一件事情很多人又不愿承认。

团队,是有风格个性的;团队,也是有能力强弱的。不管你承认不承认,整体来说,我见过的绝大多数团队都还远不是精英团队,因此相对于某些公司成功的案例来说,我们有很多事是不适合做的。

敏捷强调了主动性,强调了沟通,事实上并不是身边所有的团队都能做好敏捷管理的,譬如一支

[……]阅读全文

你会怎样设计铁道部购票网站?

1 最近铁道部购票已经成为了热点话题,毛病多得一塌糊涂,如果让你来设计铁道部购票网站,你会怎么做?

 

这样的网站属于实时性要求较高、并发性要求非常高、容量要求一般的类型,以下是我简单的想法:

 

1、部署是基于CDN的,对于车票查询的环节来说,这是没有问题的。

 

2、数据库表设计上面,应当有一张车次表,每行代表一趟车,至少有这样的字段:还剩多少张,已被锁定多少张。

 

3、每次发生订票操作时,先去查询当前是否有余票,有的话锁定一张等待用户操作,如果半小时内无法完成,锁定票放回。

 

4、查询部分,集群中放置分布式缓存,存放数据的静态页面,但由

[……]阅读全文

贫血模型和充血模型

这两个概念是早些时候Martin Fowler总结出来的两种常见模型设计类型,没有说谁好谁不好,为不同的模型类别选择合适的场景是设计者的工作。没有工具本身的问题,只有工具使用者的问题。

 

 

贫血模型是指领域对象里只有get和set方法(POJO),所有的业务逻辑都不包含在内而是放在Business Logic层。

 image

 

优点是系统的层次结构清楚,各层之间单向依赖,Client->(Business Facade)->Business Logic->Data Access Object。可见,领域对象几乎只作传输介质之用,不会影响

[……]阅读全文

由后端来类比前端设计的思考

design 有这样一句话被提起:

前端也有MVC,DOM树就是这个M,CSS就是这个V,至于C,非JavaScript莫属。

很高兴团队中有越来越多的人能够跳出某种语言、某种平台的局限性,站到抽象的层次上思考一些设计上的问题。在我的印象中,似乎前端开发总是容易给人以随意、混乱的感觉,可真的是前端技能不容易掌握吗?

大学里Java课程正儿八经学了3年,JavaScript只字未提,只是课余时间凭借着兴趣自学,加起来也就两三个月。

前端代码更加灵活,无论是HTML、JavaScript还是CSS,似乎任何一个初学者都可以轻松入门。可是越是看似简单的东西,就越难以精通地掌握,没有好

[……]阅读全文

不,这样的DTO!

R.Martin 本文翻译自 Oh No! DTO! by Robert C. Martin,这篇文章很短,强调的内容简单得不能再简单,也许大家早就意识到,但是,我依然可以在很多产品的代码里面找到文中所说的“教条”的影子,我说不清为什么,在这里有激烈的讨论,你们说呢?

 

本周我在教授XP(极限编程,译注)的课程,我们要写给当前的应用写FitNesse(一种测试工具,译注)的基础测试代码。其中一位程序员使用了RowFixture(一种测试结果比较的工具,译注),这种工具需要使用DTO(数据传输对象)并且要求其中的变量都为公有的。这时候这位程序员提出了质疑:“DTO应该使用私有的变量和一套相应的get

[……]阅读全文

API风云录

1 好吧,我承认我是标题党,还是让我们从一个故事开始吧。

项目的业务逻辑层需要被设计成一个具备易扩展的模式,对外提供了大小相异的API。项目组人人头脑风暴,最后在各位的努力下,克服苦难,业务逻辑层被封装起来,一组最初的API被提供出来:

1、现有Service逻辑已经疏于管理,欠缺重构,变成了不易控制的逻辑层,接口众多,鱼龙混杂,难以规整出清晰、可用的接口给第三方(例如下游定制团队),怎么办? 
Web应用有个特点,当你对代码的管理缺乏控制而搞不定时,可以在其上封装一层,这是一个通用的解决办法,也是一柄双刃剑。 
正如某同事“我们都是工程商人&rdqu

[……]阅读全文

Flash Scope

项目中遇到了一个潜在的问题,大致就是说,在一个流程的两个或某几个环节中,需要短暂地存储一部分对象(如果不存储,就需要在这几个环节中多次调用同一个外部接口,这被认为是不够合理的实现)。

而这部分对象的存储:

(1)如果用request,太小,毕竟一次提交以后就丢失了,如果需要往后传递,可能需要借助一些页面参数传值等丑陋或是不易控制的方法;

(2)如果用session,太大,我不需要在整个用户会话生命周期内使用,而且如果同个用户并行地操作两个流程,期间会互相影响到。

其实在Rails/Grails里面就已经包含了一个机制,它将对象短暂地放置在session中,request-response连续的

[……]阅读全文

back to top