更新时间:2024-03-30 13:59
在20世纪的60年代后期以及70年代早期,计算机程序员随意使用他们能够使用的任何方式来写软件是件非常常见的事情。
很多程序员竞相写出复杂得对于任何人来说都无法理解的软件。
如果有一个程序,它没有任何的bug,在那时可称得上是个奇迹。
大家都认为让计算机有用武之地是个有价值的追求,不能说不象老早的西部冒险之旅。
Edsger Dijkstra于1968年给CACM(应该是Communication of the Association for Computing Machinery: 计算机器 协会 通信)写了一封题为“GOTO语句其实有害”的信。
自此,软件工程的主要概念开始成型。
那时大家认为更全面、更严谨的方法可以帮助我们创建品质可靠、成本可准确估计的软件。
无法无天、牛仔式的编码者们被悬崖勒马。
20世纪80年代正是计算机程序员们的好时光。
我们有了一些规则和惯例。从质量上讲,我们这时写的软件远远优于仅仅是写于几年前的软件。
似乎可以认为:如果能够建立足够多的规则,可适用于所有能够碰到的问题,我们就能够写出完美的软件,并且还能按时完工。
于是乎就有了越来越多的、适用于所有潜在问题的规则和惯例,
现已进入了21世纪,我们发现,这些规则遵守起来非常困难,其过程很复杂,也没有得以透彻地理解;使用各种抽象符号写就的、海一样的文献犹如脱缰的野马纷至沓来。
大家热火朝天,都想提出更全面、更好的方法,跟California(加利福尼亚,加州)淘金热似的真有一比;每个到了西部的人却都很失望。
我们写出了能够帮助我们写软件的软件。
但是,这很快就乱了套,各种重磅炸弹似的CASE工具迎面而来。
这些工具原本是用来帮助我们遵守规则的,可它们用起来很是困难,简直都没法用。
要按时完工,计算机程序员发现他们必须抄近路,忽略一些重要的惯例。
实际上没有一个人真的遵守那些曾经用来自缚的重量级方法。
牛仔又回来了,我们回到了俄克拉荷马州(译者注:俄克拉荷马州是偶对OK的猜测,因为偶了解到俄克拉荷马州曾经是往美国西部输出劳工的一个大州,但可能有误,呵呵)的畜栏之中。
当程序员忽略了他们的方法中的规则时,他们(实际上是)本能地脱离重量级方法,回到了早期较为简单的、轻量级方法时代,很少的规则便够了。
可我们并不想忘记我们已经学到的东西。
我们可以把(能够)帮助我们写出高质量软件的规则保留下来,而摒弃哪些阻碍我们前进的哪些规则。
我们可以对那些复杂得难以遵循的规则进行简化。
我们也不想回到早期根本没有任何规则可言的牛仔式编码时代。
而是让我们止于足够能使我们的软件可靠、适度定价的规则吧。
我们接受软件行政长官而不要牛仔式的编码者;我们作为团队工作在一起,反应敏捷,仅仅用那些轻量级的、简练的和有效的规则和惯例把我们武装起来。
极度编程(XP)就是若干这种新式的、轻量级的方法之中的一种。
XP具有若干规则和适当数量的惯例,且所有这些遵守起来都很容易。
XP是一种干净简洁的环境,它形成于对到底是哪些东西能够加速软件开发,以及哪些东西却起着减速作用的观察。
它是一种使程序员能够自由发挥其创造力和生产力,却同时有保持组织性和凝聚力的环境。
A software methodology is the set of rules and practices used to create computer programs.
A heavyweight methodology has many rules, practices, and documents.
It requires discipline and time to follow correctly.
A lightweight methodology has only a few rules and practices or ones which are easy to follow.
In the late 1960s and early 1970s it was common practice for computer programmers to create software any way they could.
Many programmers excelled at creating software too complex for anyone to understand.
At that time it was a miracle if a program ran without any bugs.
Making computers useful was considered a worthy quest and not unlike an adventure into the old west.
In 1968 Edsger Dijkstra wrote a letter to CACM entitled GOTO Statement Considered Harmful.
The central ideas of software engineering were being born.
At that time we believed that bigger, more disciplined methodologies would help us create software with consistent quality and predictable costs.
The lawless cowboy coders were being reined in.
The 1980s were good times for computer programmers.
We had a few rules and practices to create software that was far superior in quality to what we were creating only a few years earlier.
It seemed like if we could just create enough rules to cover the problems we encounter we could create perfect software and be on time.
We added more and more rules and practices to cover all the potential problems.
Now in the 21st century we find these rules are hard to follow, procedures are complex and not well understood and the amount of documentation written in some abstract notation is way out of control.
Trying to come up with a bigger and better methodology was like a California gold rush; everyone headed west only to be disappointed.
We created software to help us create software.
But this quickly got out of control and dreadnought CASE tools were born.
These tools, originally created to help us follow the rules, are too hard to use themselves.
Computer programmers find it necessary to cut corners and skip important practices to stay on schedule.
No one is actually following the heavy methodologies we have handcuffed ourselves with.
The cowboys have returned and we find ourselves back at the OK Corral.
When programmers ignore the rules of their methodology they are instinctively moving away from heavyweight methodologies and back toward an earlier, simpler time of lightweight methodologies when a few rules were enough.
But we don't want to forget what we have learned.
We can choose to keep the rules that help us create quality software and throw away those that hinder our progress.
We can simplify those rules that seem too complex to follow correctly.
We don't want to return to the early days of cowboy coding when there were no rules at all.
But instead let's stop at just enough rules to keep our software reliable and reasonably priced.
Instead of cowboy coders we have software sheriffs; working together as a team, quick on the draw, armed with a few rules and practices that are light, concise, and effective.
Extreme Programming (XP) is one of several new lightweight methodologies.
XP has a few rules and a modest number of practices, all of which are easy to follow.
XP is a clean and concise environment developed by observing what makes software development go faster and what makes it move slower.
It is an environment in which programmers feel free to be creative and productive but remain organized and focused.
原则及原理
依赖注入
最新一代容器称为轻量级容器,它们使用一个共同设计原理:依赖注入。 对这个简单思想来说,这是一个复杂的术语。依赖注入让您将对象和它所依赖的东西交给第三方。然后第三方创建所有对象并将它们绑在一起。比方说,称为 myDao 的数据访问对象需要一个称为 ds 的数据源。那么该容器会一同创建它们,并设置一个属性:
清单 1. 创建一个第三方汇编程序
myDao = new Dao();
ds = new DataSource();
myDao.setDataSource(ds);
当然,不创建这种第三方汇编程序的话,您也可以使用框架来做其他附加的工作(如提供配置支持)。Spring 框架、Pico 和 HiveMind 就扮演了这个角色。其他像 JavaServer Faces(JSF) 框架也利用了依赖注入。
面向对象编程
使用面向方面编程(AOP),您可以编写通用的功能性模块(称为方面) —— 例如,日志、事务、安全或持久性。AOP 使您可以将这些方面联系到 POJO,然后指定一个时间点(如方法开始时或产生异常时)和另一个需要联系的方面。例如,您可能想要创建一个外观事务对象。您可以在调用方法时将 TransactionBegin 方面关联到外观方法。然后在产生异常时将 RollBack 方面关联到外观的异常。最后,在方法结束时将 Commit 方面关联到外观的方法。您在配置中完成这些工作,而不是通过编写代码。依靠这种能力,您可以创建一个简单的 POJO 事务、安全或远程访问。
您现在已经得到了关于 POJO 的声明性事务,这对企业应用程序非常有用。使用这些工具,您可以完全放弃 EJB,或者最小化它的作用。而这正是轻量级组件所要做的。
透明持久性
持久性也是建立在较简单的编程模型之上。透明持久性框架通过配置而不是编写代码,来使您为应用程序添加持久性。因为大多数应用程序是面向对象的,并且访问一个关系数据库,所以一些专家断言,我们最终将进入对象关系映射的时代。我发现的顶级持久性解决方案是 SolarMetric 的 Kodo JDO 和 Hibernate。在后面的文章中我将详细比较这些解决方案。其他轻量级解决方案,例如 iBATIS 和 Active Record 设计模式,根本不会试图进行对象关系映射。
如何减轻容器
Java 行业经历了类似的情况。EJB 技术提供了核心的企业服务。如果您曾对一个复杂的、基于组件的模型编程,您会将业务组件放入一个容器中,该容器提供诸如事务、远程控制、安全和持久性之类的服务。
然而,这里存在一些开销。重量级架构对于解决许多问题都过于复杂。例如,实体 bean 会让您为每个实体编写 7 个文件。因此 EJB 技术就不值得用来解决日常问题。如今,许多业务仍然需要企业服务,但它们正在寻找达到该目标的新方向。它们使用轻量级容器。实际上,最新的 EJB V3.0 标准就使用了轻量级容器模型。
什么是轻量级容器?
大多数容器 API(如 EJB API)强迫您编写一些接口或一个组件模型。将您的组件放入该容器后,容器会为您处理一些事情。EJB 容器提供企业服务。Servlet 容器(例如 Apache Jakarta Tomcat)实现了 Servlet API,使您可以将动态内容建立到服务器页面中,该页面随后会被发送到 Web 浏览器。
传统容器强迫使用指定的编程模型,轻量级容器则不是。它们使用普通 Java 对象(plain old Java object,POJO)。容器然后将 POJO 绑在一起,并将服务与它们相关联。
Spring 露出水面
Spring 是什么?
您若是一名企业程序开发人员,Spring 会令您事半功倍。但它到底是什么?对于这样的综合性框架,很难轻易找到一个明确的答案。从本质上讲,Spring 是一个轻量级容器。您可以通过 Spring 来利用普通 Java™ 对象(POJO)编程,使用依赖注入解析 POJO 间的依赖性,然后使用面向方面编程(AOP)将服务与它们相关联。
Spring 也提供了许多胶水代码,这使您可以更加轻松地使用 Java 2 平台企业版(J2EE)服务,比如用于事务的 Java 事务 API (JTA)、用于远程控制的远程方法调用(RMI)、用于管理的 Java 管理扩展(JMX)或用于持久性的 Java 数据对象(JDO)。Spring 还为开放源码框架,比如 Hibernate、Tapestry、Struts 和 JavaServer Faces(JSF),提供了胶水代码。注意,虽然有些框架是相互竞争的,但这并不是什么问题,Spring 没有试图只支持一种获胜的框架。
容器比较
本文介绍合力完成一种不同的活动:应用程序开发。敏捷开发流程,比如极限编程(Extreme Programming,XP)和 Scrum,寻求降低流程开销。尽管存在许多不同的流程,但它们当中都有一些共同的趋势:
越来越重视客户参与,而非重量级需求文档
通过重构改进质量和设计;重的、自动化的单位测试;连续集成
小团队,较少的正式沟通和更多的非正式沟通(15 分钟的站立早会,更多的配对编程)
短而一致的周期,最后是客户反馈
敏捷方法剔除了不需要的流程,直到只留下完成工作所必需的流程。尽管许多编程人员理解轻量级、敏捷方法的强大功能,但许多管理人员习惯使用更传统的流程。如果您认为敏捷可以帮助您,那么通过应用下列思想来学习如何协调传统管理与敏捷开发流程:
将您使用的语言改为侧重于原则,而非流程。
创建小而灵巧的团队。
重视可测量的交付。
重视简约性。
重构代码并自动化测试。
获得客户反馈。
原则而非教条
当编程人员或架构师试图将敏捷流程注入保守公司时,最好是抛开教条 —— 即,将重点放在原则而非教条上。如果您对 XP 的优点大肆吹嘘 10 分钟,典型的老板会关注一个词 极限。因为老板关注的是减轻风险,所以您注定失败。相反,您可以挑选一些您的管理层想要解决的问题。然后,选择敏捷原则来帮助解决这些问题。
敏捷开发
本文介绍合力完成一种不同的活动:应用程序开发。敏捷开发流程,比如极限编程(Extreme Programming,XP)和 Scrum,寻求降低流程开销。尽管存在许多不同的流程,但它们当中都有一些共同的趋势:
越来越重视客户参与,而非重量级需求文档
通过重构改进质量和设计;重的、自动化的单位测试;连续集成
小团队,较少的正式沟通和更多的非正式沟通(15 分钟的站立早会,更多的配对编程)
短而一致的周期,最后是客户反馈
敏捷方法剔除了不需要的流程,直到只留下完成工作所必需的流程。尽管许多编程人员理解轻量级、敏捷方法的强大功能,但许多管理人员习惯使用更传统的流程。如果您认为敏捷可以帮助您,那么通过应用下列思想来学习如何协调传统管理与敏捷开发流程:
将您使用的语言改为侧重于原则,而非流程。
创建小而灵巧的团队。
重视可测量的交付。
重视简约性。
重构代码并自动化测试。
获得客户反馈。
原则而非教条
当编程人员或架构师试图将敏捷流程注入保守公司时,最好是抛开教条 —— 即,将重点放在原则而非教条上。如果您对 XP 的优点大肆吹嘘 10 分钟,典型的老板会关注一个词 极限。因为老板关注的是减轻风险,所以您注定失败。相反,您可以挑选一些您的管理层想要解决的问题。然后,选择敏捷原则来帮助解决这些问题。
持久性策略
选择合适的工具
对于带 i-drive(它投入更多的力量到踏板曲柄而不是弹起的后避震)的山地自行车、低容量的皮划艇(它让我使用河面下的水流)和框架,我有着相似的经历。当我的客户处理持久性时,为他们找到合适的框架可以把一个艰难挣扎的、沮丧的团队转变为一个运转良好的机器。但是,您必须小心。改变框架可能是昂贵的。本系列的 第 3 部分 展示了 Spring 如何帮助您优化诸如持久性(persistence)之类的服务。本文则关注寻找合适的持久性框架。首先,让我来破除几个神话。
神话 1:技术总是最要紧的。
不论您是在谈论 RDBMS 还是持久性框架,持久关系都是长期的。您需要知道您选择的方案将长时间拥有市场份额。如果不是,您将冒着被迫离开指定框架的风险,而这并非您的意愿。
神话 2:对象关系映射程序(Object Relational Mappers,ORM)隐藏了所有的数据库问题。
持久性框架简化了一些问题,但引入了一些其他的问题。如果您不理解底层架构,那么找懂的人问,或者不要使用对象关系框架。
神话 3:JDBC 总是比 ORM 要快。
当然了,一个非常协调的特定 Java 实现总是会打败普通的 ORM,但是您很难找到一个非常协调的 JDBC 应用程序。JDO 和 Hibernate 之类的框架提供许多方法来提升性能。
神话 4:ORM 总是合适的工具。
常常,您会发现要求更好的访问 SQL 的问题。您也会发现面向批处理的而非交互式的问题,或要求直接访问数据库行,而非完整的对象模型。这些问题并没有充分利用 ORM。更糟糕的是,一些解决方案也许会碍事。
Java 替代方案
在给 Java 技术飞艇戳几个洞之前,我应该提醒您一点儿历史。Java 编程语言来自一个没有希望的来源(Sun Microsystems),为了与控制服务器端的统治语言(C++)竞争,那时一个程序设计范例正在寻求摆脱困境的办法(过程客户端 - 服务器代码)。互联网爆炸,突然带有内置 Java 虚拟机(JVM)的 Netscape 出现在每个桌面上。为了被广泛接受,Java 语言向 C++ 社区做出了几个重大妥协:
像 C++ 一样,它是静态类型,而不是像 Samlltalk 那样的动态类型。
像 C++ 一样,它允许原语和对象。
它涵盖了 C++ 的语法和控制结构。
为了获得市场,Sun 保留了与 C++ 足够接近的东西来吸引社区。Java 语言没有必要比所有其他的面向对象语言都好。它只需比 C++ 好就行了。现在,其中的一些妥协开始损害 Java 语言。
闭包
Java 语言允许比 C++ 更高的抽象,比如管理内存和字符串。但是,要达到像 Ruby 或 Smalltalk 语言那样高的抽象,Java 语言还有很长的路要走。以迭代为例:用 Java 技术来完成一个数组的迭代,要这样写:
Seaside
用 Smalltalk 编程?
Avi Bryant 使用 Ruby 编程语言创建了一个基于 continuation 的服务器,但是留下了 Smalltalk 的 Squeak 方言 —— 20 世纪 70 年代的初期,当 Ruby continuation 被证明是不太稳定(后来被修复)的时候,发明的一种纯面向对象的语言。然后他在 Smalltalk 的Squeak 方言上建立了 Seaside 框架并再未回头。他现在使用 Seaside 为客户快速地建立 Web 应用程序。他们愿意采用诸如 Squeak 之类的语言是因为这个框架的生产效率非常高,大大降低了开发的总成本,并提前了产品进入市场的时间。
Continuation 框架
使用 Java™ 编程语言进行 Web 程序开发与骑自行车这个例子有几分相似。我们总是把原本简单的事情复杂化。您需要确保一切无状态,才能获得更好的可伸缩性。如果以 Servlet 或 JavaServer Page(JSP)的形式为用户请求编写多种独立响应,就会留下许多散乱无章的独立请求/响应块。每个块都需要确定其在整个应用程序上下文中的位置。您必须绕过前进路上的每一块小石块,牢记各请求的状态。如果顾虑得过多,在用户单击 Back 按钮、打开第 2 个会话或者是尝试直接转到一个较旧的 URL 时,您会发现自己“从把手上方翻了出去”。您希望可以假设用户将按正确的顺序执行任务,但这显然是不可能的。绝大多数 Java 框架都不是以这样的方式运作的。
本文将向您介绍一种完全与众不同的 Web 服务器:基于 continuation 的 Web 服务器。当然,Java 编程语言没有为 continuation 提供内置支持(但其他编程语言有这样的支持)。这里,我将就基于 continuation 的服务器进行讨论。在 “轻量级开发的成功秘诀:第 8 部分” 中介绍了一种名为 Seaside 的此类框架,还介绍了一些可通过各类创新方式提供有限的 continuation 支持的 Java 技术框架。