业务域,是软件的核心价值所在。
敌人还是朋友:项目经理和架构师
无论是买成型的软件产品,还是出资开发项目,客户投资的是软件的业务价值。项目经理直接为这个目标负责,尽量少的成本,尽量短的时间,生产出高业务价值的软件产品。架构师则是跨越单个项目,长期为这个目标负责。
项目经理与架构师是天生的敌人,短期看这是对的,长期来看,他们是真正的朋友,是战略朋友。没有项目经理项目会死得很快;然而没有架构师,公司会死得很惨。
项目经理的角色和作为,我仍比较容易理解。一则,他以短期为目标,人都是短视的,所以项目经理的角色比较接近人的直觉;二则,项目经理的活动也是我们常见,常说的,例子故事较多。而对架构师,我们却颇多误解,至少也是含混不清。
我曾经问过很多开发人员,你的五年计划是什么?几乎无一例外的回答都是想成为一名架构师。特别是在校学生,几乎是脱口而出。这是一个有意思的现象。我的理解,一、他的职业方向是技术方面,想在技术上有所建树,架构师是一个明显的技术标杆,从这一角度,我很肯定他们的回答。二、业界对软件职业两条线,项目轻理和架构师,这个理论已经深入人心,也不错。三、架构师成为脱离“开发苦海"的代名词,颇值商榷。
架构师不是一个只管"架构"的家伙,他更是一个集大成者。各种技术,无论高雅还是低俗都是他囊中的武器。还有低俗的技术吗?有的,非常多连刚入门的开发者都觉陈旧的好东西。
什么,继承,你老土了吧?开口只会说设计模式都不敢说你是做开发的。现在,都是云,云开雾照的云。NoooooSQL一听这名字就得劲。否定错误就是正确,这世上哪有没有瑕疵的东西。所以,我们的口号就是否定一切!好了,扯太远了。
是的,架构师的工具箱中应该有琳琅满目的各种称手的工具。但这只是从一个视角看架构。我们很多时候盯这些工具本身盯得太紧。看工具或者技术本身,如何的眩丽、如何的酷毙。今天,我们来换个角度,看看工具和技术的目标,他为谁服务?
从Repository到Domain
首先,仓储模式(Repository)。Repository不是DAL!虽然它们如此的接近,有的架构设计就把它们合二为一了。Repository用于对象持久化,DAL是从数据库中操作数据。仍然迷惑,看不出两者的区别?
让我们来一个思维的游戏:
- 一般三层架构的文章用来解释DAL层的好处,用数据库的变更做例。比如:之前系统是用ORCAL数据库,现在要换作SQL Server。如果,我们使用了DAL这一层,就可以很容易实现,而不触及系统其它。
- 我这里需要你设想另外一种变更,从数据库存储数据,切换到用文件系统,如CVS或XML文件放数据(如果你要想的更高级一点,更酷一点,可以想想用云储存)。这时候,DAL这一层的隔离已经没有办法解决了。而是要更上层,这就是我们的Repository。
所以,可以说Repository和DAL是两层。自然,这增加了复杂度,你确实需要衡量你系统是否必要。另外,nHibernate可以很好的担当了DAL的角色,同时对Repository的支持也很好。应用得当,可以减少很多工作量。
再回到Repository的描述,Repository用于对业务域对象持久化。细心的人可以发现,我加了三个字”业务域“。
从MVC到测试
其次,MVC。MVC不是三层架构。虽然看起来它也分三块,但决对不是。另外,MVC中的M不是业务域,决对不是,虽然有些系统实现采取了这种方式,把MVC的M和业务域对象合二为一,但是原则上它们完全不是一回事。微软用VM(View Model)代替M还是有点意思的。
MVC最大的目的和功能,是把最终界面相关(V的部分)的东西最大限度的隔离出去,因为这部分是不可测试的,而那些仍然与界面相关,含有大量逻辑(算法?)的部分抽象出来,或者放入C中,或者放入M中。使得可测试的代码的边界,尽可能推到UI的最前沿。虽然,慢慢现有不少UI测试自动化工具的出现,功能还不错,但是与单元测试,代码直接接口的测试相比,效率和质量还是不可同语。
仍然回到对目的的思索。MVC是为什么?为了测试?恐怕还不是最终的目的,测试又是为了什么呢?
从自动化测试到Domain
单元测试,行为测试,集成测试, 众多名词,我不想讨论它们之间的差别,作为一类概念,从名称上,他们只呈现了一半的内涵。还有一个重要部分被漏掉“自动化”。自动化单元测试, 自动化集成测试,才更为准确。自然,这里我也不讨论非自动化测试,如功能测试,验收测试。
自动化测试的好处是不言而喻的。前文中MVC提到的测试,就是指提高自动化测试的覆盖率。对整个系统来说,达到100%的覆盖率是根本不可能的。在这个大前提下,我们很容易忽略提高自动化测试覆盖率的重要意义。90%与70%只是数字的区别?让我么走近一点,把系统拆分一下再看。整个系统不能达到100%,具体是那部分不行呢?前面提到的View是一个,数据库又是一个,不是完全不能测,理论可以,实际有些麻烦,不值当。还有就是一些外部功能,如发邮件,读写文件。文件操作这个看来经常用到的功能块却是单元测试的大敌。所有这些排除后,再回头看看,我们可以说剩下的100%能测试,也必须测试,不然就是架构和设计的问题。
剩下的这100%中,很大部分就是业务领域模型,重中之重,难中之难,也是值中的超值。
代码工厂=CRUD?
前面的Responsitory也好,MVC也好,看似复杂,其实简单,简单在于逻辑固定。昨天,我花了一个小时,完成了一个简单类的添加,现实的功能,从前端controller(我叫command)到服务层,业务类,再到Respository及数据库,只花了一个小时。因为逻辑简单固定,相当于一个表的CRUD。很多推广的所谓一站式解决框架,都是用这种情况的典型案例,特别是微软,从VB开始,到现在的Entity Framework,最酷的演示就是只要添加几行数据定义,一分钟,从界面到后台完成。当然,这比我昨天的手工作业要快得多。但是回到实际的商业软件开发,从来没有基于这样的高效而能一天完成一个项目。不是吗,如果按一分钟一个界面或者一个数据表,一个有100个表的项目已经足够大了吧?这样简单做个乘法,我们不是100分钟就可以搞定了吗?实际呢,不用说100分钟,就是100个小时也不够。所以,这样的演示根本没有含义,可是,很多人却乐此不疲。
我以前公司,有一位架构师,在iBatis的基础上,完成一个所谓框架,可以已经创建的数据表,自动生成业务对象,和CRUD的代码。然后骄傲的宣布,80%的开发工作已经完成。可是之后,项目又开发了两年。如果说是80%的代码量,我可以说是,80%的工作量?我怀疑。
这正是我们很多架构师没有意识到,或者不愿意承认的事实,框架设计好了,架构搭建好了,这才刚刚是个开头,而远远不是结束。
这是百般武艺亮尽的结束, 是业务领域探险的启程。
下一篇文章,可能会拿出一个业务领域的经典例子来看看:年月(YearMonth)和时间段(Range)。是否有兴趣?