UML软件工程组织

成功的软件管理方式:指导与平衡
作者: Walker Royce

本文介绍了管理一个软件产品与管理一部电影作品的若干对比,然后讨论了从成功项目中获得的四种软件管理方法。

使用传统的工程管理原则管理软件项目是很难取得成功的。把软件管理的挑战与制作一部动作大片进行比较,我们会发现很多有趣的观点。两者的管理问题都集中在在受经济因素制约的环境下进行复杂的集成知识产权的开发。本文介绍了管理一个软件产品与管理一部电影作品的一些对比,然后详细介绍了从成功项目中获得的软件管理的四种方法。主要的推荐做法是使用指导性的领导方式,而不是传统理念上的事无巨细的计划-轨迹领导方式。

在我的职业生涯中,我有机会观察并评估了上百个软件项目,它们广泛覆盖了各种工业和应用。一个显著的成败决定因素是在项目从初始到被用户接受的过程中所采用的项目管理方式。

根据我的经验,如果软件项目管理者使用更像是管理一部电影作品的方式,而不是管理一个工程产品的方式,那么他们似乎更容易成功。“胡说!”有人可能反对。“软件项目需要更多严格的工程管理,而不是更少!”在你发表你的言论,向权威发出挑战以前,请考虑以下观察资料:

大多数软件权威不需要物理定律或者物质属性来制约他们的问题及其解决方案。他们只是受到人类想象力、经济因素的制约,以及当他们获得一些可执行程序时,他们受到运行平台性能的制约。一些嵌入式软件的开发者显然是例外者。
在一个软件项目中,你几乎可以在任何时间改变任何东西:计划、人、预算里程碑、需求、设计、测试等等。需求——可能是我们的工业中被最严重误用的词——很少能描述出真正需要的任何事情。一切几乎都是可以协商的。
软件产品的评估和衡量没有原子单元。经济性能(在服务行业中更为典型,评价为性价比)被证明是最好的成功的度量手段。质量的大多数方面都是很主观的,比如可维护性、可靠性以及可用性。

这些观察结果对电影制片人同样适用,他们是有规律地创作独特的、复杂的、只受视角和人类创造性制约的知识产权作品。我假设电影作品的经济性能与软件项目的经济性能是相似的:从2000年起,只有三分之一作品的发行带有时间或经济上的可预言性。1我知道这些观察在使用工程理念来制造飞机、桥梁、心脏移植管、核反应堆、摩天大楼以及卫星的项目管理者看来是不入流的(除非这些工程项目包括重要的软件内容或是空前的,史无前例的系统)。

好的,有人可能会说,软件只是一个未成熟的工程分支,在我的职业生涯中,大约每五年软件项目的底层技术就要翻新一次。这些翻新包括语言、结构模式、应用、用户界面、计算平台、网络、环境、过程以及工具。这种快速持续的进化将要放慢了吗?目前还看不出这种迹象。人类想象力和市场作用仍是非常强大的。

就像电影工业,我们需要有资格的建筑师(导演)、分析家(编剧、设计师)、软件工程师(产品工作人员、编辑、特技制造者、演员替身)以及项目管理者(制片人)。还是和电影工业一样,我们必须使软件成为可执行形式(弄到胶片上)来切实进行进度和质量的评估。在我们发现什么可用什么不可用的过程中会产生大量的碎片和重复工作,然后我们把很多人的贡献集成为一个紧密集成的知识产权作品。

我所认识到的是,软件管理应被更精确地描述为软件经济的一个分支,而不是软件工程。软件管理者每天的决定(正如电影制作人每天的决定),主要是由价值判断、成本权衡、人为因素、宏观经济趋势、技术趋势、市场强度以及时机控制的。软件项目很少注重于精确的数学、物质属性、物理定律或是其他已经建立的成熟的工程原则。

我希望这一对软件-电影的对比刺激了你的神经,使你想继续读下去。如果想了解更详细的对比请参考 Paul Graham 的论文。2下文着重介绍的是一些从软件项目中获得的断言,这些项目包括了我在25年多的时间里在软件项目管理领域跟从、领导、实践、指导的少数成功软件项目和大量不成功软件项目。

迭代的方法

造成软件集中型项目的低成功率的原因之一是传统的项目管理方法不鼓励进行指导和调整以缓解以下问题的不确定性:

问题域(用户究竟想要或者需要什么)
解决域(何种结构和技术的组合是最适用的)
计划域(成本和时间制约、团队组成和生产力、涉众交流、递增结果序列等等)

我们需要一种更为动态和具有适应性的方法来思考软件进程和质量管理的问题,这种方法应当适应成功项目的模式。当今的现代软件管理方法3-5 通常被称为迭代 开发方法。在现今充满不确定性的软件应用程序、产品和服务开发的雷区中,迭代方法指导了软件项目,而不是遵循一个精确的、长期的计划。按时间和预算计划成功发布软件产品需要一种发现、生产、评估和指导性领导方式的进步的混合。“指导”一词意味着积极的管理参与,经常的过程矫正以产生更好的结果。所有涉众应该通力合作,集中实现不断前进的目标。

作为一个被广泛接受的现代迭代开发过程,IBM Rational Unified Process,6 为一个更为平衡的发展提供了一个框架,这一发展是鼓励对不确定性和风险进行管理的。它的生命周期包括四个阶段,每个阶段都有可演示的结果:

1.起始:远景和商业案例的定义和原型设计
2.细化:对架构基线进行集成、论证和评估
3.构建:对有用的增量进行开发、论证和评估
4.产品化:可用性评估、最终产品以及发行

阶段的名称表现了项目的状态,而不是从需求到设计到编码到测试到发行的基于顺序性活动的项目进展。

我们把这一迭代管理方式称为基于结果的,而不是基于活动的。在软件世界中,真正的结果是可执行程序。其他的任何东西(需求文档、用例模型、设计模型、测试用例、计划、过程、文档、检查)都是次要的,而且只是实现目标——一个可执行的软件程序——的手段的一部分。回想你做程序员的日子:当你在建立一个模型、画流程图草图、推理一个状态机的逻辑或是写源代码的时候,你知道你只是在思考和集成一个抽象方案。只有当你编译、链接和执行时方案才变得切实可行。项目管理者应该有同样的感觉。当你评估一个计划、模型、文档或一些其他不可执行的表现物的美好和出色之处时,你只是在推测项目质量和进度。电影制作人对剧本、情节串连板、背景设置以及服装设计的感觉也是如此。他们着力于影片的每一个镜头,使得电影成为可以判断总体集成效果的实体。

精确度与准确度

在一个成功的软件项目中,每一个开发阶段都加深了对发展计划、规格说明和完整解决方案的理解,因为每一个阶段都延伸了可执行序列和团队对竞争目标的认识。在生命周期中的任意一点,次要工件的精确性应与这种理解相平衡,在详细程度上保持一致,相互之间保持一定程度的可追踪性。

精确度与准确度之间的区别(在软件管理的上下文中)并不是它们看起来那样小。软件管理充满灰色的区域、情景依赖性以及不明确的折衷。对优秀的软件管理者来说,理解精确性与准确性之间的区别是一种基本技能,因为他们必须准确地对投资、风险以及变化带来的影响进行预测。未被证实的精确度——在需求或是计划内的——实际上是造成阻碍成功的潜在而微妙的因素。大多数时候,早期的精确性是不诚实的,造成了有比实际上更多的进展和更高的质量的假象。不幸的是,很多项目发起者和涉众要求这种早期精确性和详细性,因为这给了他们对已经取得的进展的(虚假的)安慰。

我在软件工业中所见的最常见的失败模式之一是开发有五位数精度的规格说明,而涉众其实对问题、方案或者计划只有一位数精度的理解。延长建立一个精确的需求理解或详细的计划的时间实际上耽误了对架构上更重要的问题的理解。你曾经做过、修改过、痛苦地回顾过多少厚度吓人的需求文档或是详细的管理计划呢?而几个月后当项目取得了有实际意义的可演示的进展,加快了涉众对实际的权衡的理解时,你又要全部重新检查这些文档和计划了。这种普遍现象在我们的行业里被称为刨光废物。

一些成功的指导模式

迭代过程大多是由解决不确定性和管理软件风险的需要而发展的。这里的指导需要动态控制以及中间的检查点,这样涉众就可以评估到目前为止完成了哪些工作,应该对目标作出什么修改,以及如何重新分配他们的工作以使目标按照最为经济的方式组合。我曾观察到成功的软件集中型项目典型的四种模式。这些模式表现了一些“抽象规格”,对指导评估、范围管理、过程控制、进展和质量控制有所帮助。我有预感,多数在项目管理中“被鉴定过的”项目管理者对此都会作出消极的反应,因为这些理念在一定程度上是与传统相悖的。

范围管理:方案从用户具体的要求发展而来,而用户的具体要求从候选方案发展而来。与从开始就确定所有需求不同。
过程控制:过程和工具的使用从轻到重渐变。与把整个项目的生存周期过程定义为轻或重不同。
进展:健康的项目展示出一个进展和背离的序列。与按照预期计划100%实现价值,没有明显的背离不同。
质量控制:测试可演示的发布版本是一个头等重要的、贯穿全生命周期的活动。与认为它是次要的,生命周期晚期的活动的观点不同。

我承认在实际软件项目中,上述四点都是说起来容易做起来难,而且对不同领域它们应该被不同地应用。网络应用程序开发团队与嵌入式应用程序开发团队实现这些模式的方法应该是不同的,但是对他们来说模式都是可用的。方法、模式和技术的书籍和论文的写作,(工业界称为思想领导),是相对简单的。尽管如此,我们中的多数人并不是在寻找最好的思想,而是在寻找最好的实践方法。管理实际项目需要实践的领导力,而在实际项目条件下应用和执行这些理念是相对困难的。我们应当珍惜懂得实践的领导力的项目管理者:他们可能是每个公司中最稀有的资源。优秀的项目管理者,就像优秀的电影制作人一样,不只是常常创造出优秀的产品,他们还是年轻团队成员的良师益友,这些年轻人能够学习有效的技术并发展他们自己在多维权衡、持续性沟通、风险管理、模式识别以及指导式领导等方面的技能。项目管理训练课程是学习的良好催化剂,但是学徒期是不可或缺的。

范围管理

传统软件过程的比较微妙的挑战之一是如何把生存周期表现为一系列顺序的活动:从需求分析到设计,编码,测试,最后发行。成功的项目确实用一种抽象的方式实现了这种进展路线,但是活动之间的界限是模糊不清的,只能被合作的涉众所接受。另一方面,不成功的项目则陷入了挣扎着寻找活动间清晰的界限的误区。比如,在过渡到设计前追求100%固定的需求基线,或是在过渡到编码前追求非常详细的设计文档,都是严格的中间目标,造成了注意力被琐碎细节所分散,而重要工程决定的进展却被放缓甚至停止。

当我们建立一个全新的软件方案时,从需求到设计的连续的详细规格说明流也许是有一定意义的。但是现在,我们通常是升级一个已有系统或者根据已有部件(操作系统、网络服务、网络、图形用户界面、数据管理、封装的应用程序、中间件、计算平台、遗留系统等)建立新的系统。改造或复用已有财产的经济效益迫使我们考虑在这些已有财产的环境和限制下的用户具体需要。

我前面曾经说过,需求可能是我们的工业中被最严重误用的词。需求意味着不可协商,但我们却在几乎所有成功项目中看到需求的变化,妥协和让步。改变一个需求需要进行大量严格的审查,因为这通常对涉众间的合同有很大影响。我建议我们使用规格说明来代替需求。规格说明是可以更改的,而且可以理解为我们现阶段对项目的认识状态。

就我所见过的而言,用户规格说明有两种重要形式。第一种是观点陈述(或用户需要),它抓住了开发团队和买方或说用户之间的合同。这些信息应以用户可理解的形式(一种包括了文本、原型、用例,电子表格等等的特殊格式)表现。一个支持观点陈述的用例模型起到了用户或买方可以理解的语言表达可操作的概念以及期望的行为的作用。

规格说明的第二种形式与需求非常不同。我倾向于使用评估标准这种说法,它被自然理解为目标的瞬间快照,而目标是一个生存周期的中间检查点,比如一个可演示的版本发布。评估标准是从观点陈述或者其他资源(制作/购买/复用分析、风险管理相关、架构方面的考虑、隐藏问题、实现限制、质量极限等等)中派生出来的中间的指导目标。它们与用例模型一起,为早期测试,而不是为传统的需求表达提供了更好的框架。一个计划的发布内容序列和计划的评估标准的初始提议就是一个风险管理计划的很好的形式。

过程严格性

多年来,我一直尝试着调解敏捷阵营(软件过程观点的自由主义左翼)和过程成熟阵营(软件过程观点的保守派右翼)之间狂热的争论。他们都有有益的观点和适当的技术。但是经过最老于世故的努力,在需要解决方案的范围内没有清晰的正确或者错误的处方。上下文环境是极为重要的,而且几乎所有不是太过普通的项目和组织都需要结合技术、常识、领域内的经验来取得成功。多数项目管理者会同意下述观点:

在我看来,最后一个观点描述了决定敏捷方法的速度和自由度,严格方法的质量和说明性指导的决定性因素。过程严格性应该与重力作用很相似:你越接近产品的发布,过程、工具、员工每天的活动使用仪器的影响就越大。你离发布日期越远,这种影响就越小。这个公理在过程里似乎完全被忽略了,或者至少是不受重视的,但是它在成功的软件项目中通常是非常引人注目的。

大多数成功的软件开发过程的一个标志性特征是详细定义的从创造阶段(初始和细化)到生产阶段(构建和产品化)的过渡过程。当软件项目无法成功时,一个主要的原因是对过程严格性不合适的强调(过多或者过少)。这种现象在传统过程和迭代过程中都是存在的。多数不成功的项目带有下列特征之一:

生存周期早期阶段(创造性方面)的过度设计。你需要有机动性的过程,该过程容易适应新发现、适应对几个主要风险和原型方案造成攻击的一定程度上的不确定性,并且建立早期的粗糙工件。你能想到哪些创造性原则,根据这些原则过程严格性对帮助人类思考被认为是有益的?
生存周期晚期阶段(生产方面)的设计不足。详细工件的广泛的变化管理基线需要带有富有洞察力的实现方法,对连贯性的密切关注,以及自始至终对产品质量聚焦的工程过程。

成功的现代项目——以及使用传统过程开发的成功项目——通常都有详细定义的项目阶段性标志,即从创造性研究状态到生产状态的显著过渡。早期阶段着重于实现可演示的功能。后期阶段着重于实现可供用户使用的产品,这种产品关注的是健壮性、性能、适用性以及完整性。

另一个重要方面是从创造性世界到生产世界的过渡对整个团队的影响。结构良好的团队通常不喜欢严格的过程、细节以及不成熟的精确性。生产能力强的团队通常会对松散的、不固定的、粗糙的结果感到不愉快。项目管理者需要管理各种团队的平衡性,这样技术上领导的重力中心就可以在整个生存周期发展进化,从初始阶段的管理团队,到细化阶段的架构团队,到建构阶段的开发团队,再到过渡阶段的测试/评估团队。软件项目管理中人的因素被低估了,而且团队动态性的主题值得被给予比今天大多数项目管理课程所给予的更多的关注。

进展

经典开发过程的很多方面造成了涉众关系退化到相互间的不信任。信任对在用户需要、产品特性以及计划中通过指导和协商取得平衡是最基本的。迭代过程加强了涉众间的有效交流(通过一系列可演示的发布实现),允许基于更为客观的所有人理解的协商。这需要客户、用户、以及管理者集中于可用系统的发布,而不是笃信标准和合同条款。它同时还需要开发组织致力于用能获得利润的方式创造价值。

迭代过程需要对一个不断完整的系统进行顺序的建构,这个系统展示了架构,实现了客观的需求协商,证实了技术方法,并指出关键风险。理想的情况下,所有涉众都着眼于这些里程碑,把它们视为有用功能的递增发布,这不同于那些投机的对最终观点的论文描述。向可演示驱动的生存周期的过渡造成了非常不同的项目外观。一个健康的项目将诚实地展示出一个进展与背离共存的序列,而不是一个线性发展价值递增的轨迹(通常是不诚实的)。

下面是两个我从未见过的反例的相关观察:

1.一个具有一张价值持续不断增长曲线图的软件项目一定会有一个待解决的很大的回归。
2.在解决不确定性,会师于一个可接受的解决方案的过程中,健康的软件项目表现为一个进展不断增加,弯路不断减少的序列。

雄心勃勃的展示是一个健康的项目的发展道路上绝好的里程碑。在生存周期早期进行展示的目的是暴露设计缺陷,不是粉饰门面。涉众不应对早期错误、背离或不成熟的设计反应过激。如果早期工程阶段受到过分限制,开发组织建立的中间检查点将不会那么有抱负。早期的增量是不成熟的。外界涉众,比如客户和用户,不能指望初始发布的版本拥有最终发布版本的规格和性能——也就是完整、完全可靠、拥有目标级的质量和性能。

另一方面,开发组织必须对连续增量之上的切实的进展负责,并对之进行展示。客观地量化变化、修改以及更新将会为进展和质量提供诚实的指示。公开和专心的追随对解决问题是必须的。好的和不好的项目性能在生存周期的早期往往更为明显。采用指导式的领导方式,成功就会孕育成功。在发布一系列可演示的结果以后,你就可以很好地预测结果了。持续没有进展或者停滞的结果序列是项目需要认真重新考虑资源、范围或者项目价值的标志。软件项目的经验已多次表明,早期阶段决定项目的成败。这就是使用小型的、能力强的出发团队处理计划和架构设计阶段工作的原因。如果这些早期阶段处理得当,项目将会由能力中等规模的团队向最终产品发展,并成功完成。如果计划和架构设计阶段处理不好,即使出动全世界的程序和测试专家可能也无法在后续阶段取得成功。

质量控制

如果你按照迭代开发的精神正在成功管理一个项目,那么多数集成测试应在部件测试之前进行。停下来思考这一陈述。尽管在任何时候都有两种活动在混合进行,你应该认识到初始的部件开发和测试更多的是作为在一个集成的、系统级的线程或行为内执行一个部件的接口和功能的方法。一旦接口和集成行为被成功测试,部件的完整性也就可以测试了。先进行集成测试加速了架构上重要的问题更早进入生存周期的相应阶段。它还为持续的系统级和部件级进展和性能的评估提供了演进的测试模板。

这种先进行集成测试的方法的一个关键副产品是测试和测试人员成了项目过程中的头等公民。在传统方法中,测试人员建立计划、过程和文档,它们都是次要于分析和设计工件的。测试人员的工作和生存周期早期的工件对项目的成功没有太多指示作用,在多数组织内都是由“B选手”(意思是,不能成为最优秀分析和设计师的人)来完成的。在健康的迭代项目中,生存周期早期的演示需要重要的测试观念和产品。很多测试团队对一些最有效的“分析”活动和结果负有责任。太多分析人员在抽象模型内单独工作,他们的分析受到的制约是有限的。但是测试人员面临的是建立“测试用例”——真实世界中用例或者评估标准或者预期行为的表现。他们提出一整套不同的问题并从一个不同的角度看世界,因为他们的工作是把抽象的东西翻译为可测试的东西。

这是一个例子。现在很多项目都面临着对商业上可获得的部件和应用程序是采取买还是自己写的办法的抉择。如果第一个面向结果的项目的里程碑是通过演示来作出自己写/购买的决定的,那么你应该对你的团队进行如下分工:

分析团队:与用户一起工作,捕捉产生最差性能的关键用例的情况,比如数据量峰值或者最关键的控制画面。
设计团队:设计可以运行候选商业部件的原型。
测试团队:构建测试用例(比如,一个消息集合、一个测试驱动、一个智能桩模块、一个有数据的数据库、一个图形用户界面操作的序列等等)。这些用例能够反映关键用例,驱动原型并记录它的相应。

为了实现这第一个里程碑,你的团队可以只关注其中两个关键用例(约为用户需要的10%)、少数几个关键部件以及少数几个测试用例,但是它们以及用户将会在生存周期非常早的时候就解决掉30%的风险。通过把测试观点作为过程早期一个同等伙伴包括进来,你将可以吸引更多作出更好分析的优秀人才,因为这项工作更为有趣,而且对成功的贡献更为有效。

传统软件测试方法遵循相同的、应用于软件开发的文档驱动方法。开发团队在建立任何源文件或可执行文件之前先建立需求文档、顶层设计文档以及详细设计文档。相似地,测试团队在建立任何测试驱动、桩模块或工具之前先建立系统测试计划文档,系统测试过程文档、集成测试计划文档、单元测试计划文档以及单元测试过程文档。这一文档驱动方法对测试活动造成的问题与它对开发活动造成的问题是相同的:对大量废物的刨光,还要留待日后重新组合整理。

为了在生存周期中提早进行集成测试,测试序列应该由迭代过程来组织,而不是根据部件来组织。典型地,它应该被一组用例和其它文本表现的、能有意义地为用户进行演示的实体所捕获。下面是一个抽象的描述:

初始迭代:大约五到十个评估标准,抓住与主要用例(对结构选择和整体商业案例有影响的)相关的驱动问题。
细化迭代:十几个评估标准,当用候选架构进行演示时,为主要用例检验实体框架,并证明关键风险已经被解决了。
构建迭代:大约数百个与有意义的用例集相关的评估标准,这些用例集通过测试以后将组成有用的产品子集,可以转为产品的alpha或beta发布版本。
产品化迭代:完整的用例集和相关的评估标准(可能有上千个),组成了与真正发布产品相关的接受测试结果的标准。

现代过程在产品的测试活动中使用的基本工具、语言、符号以及工件与在产品的开发过程中使用的是相同的。测试是指对某些组件在一个控制情境下的执行以及期望的客观结果的外在评估。一个测试的成功取决于在一般意义上定义的成功标准下期望结果与实际结果的比较情况。测试就是可以大规模自动化由机器完成的评估形式。

总结

图1提供了项目管理者对改进时间和价值过渡的观点,我们都应该努力实现这一理念。它为概括有效实现指导式领导(我在四项推荐中所暗示的)提供了一个很好的抽象视角。我通过画出开发进度-时间图展示了三个项目的外观,其中进度是用可执行百分比定义的,也就是用目标的可演示形式。在这个意义下的进展是与结果确实相关的,正如我前面描述过的,而且通过可执行演示是很好度量的。可执行不意味着完整、适应或是符合规格;但是它确实意味着软件是可测试的。

当使用这种度量方法时,典型的传统工程项目管理风格序列是(1)通过文字设计和详细(经常过于详细)工件实现的早期成功,(2)承诺在生存周期后期完成可执行代码,(3)由不可预见的实现问题和接口二义性造成的集成噩梦,(4)使系统工作起来的巨大的预算和时间压力,(5)末期不甚理想的产品,没有时间进行重新设计,最后(6)一个脆弱、不可维护的产品推迟发行。

我这里介绍的现代管理方法把集成加入到了设计阶段,并经过一系列可演示的版本发布,于是也就使得架构上重要的缺陷更早出现,能够在生存周期目标的上下文中被解决。顺流而下的集成噩梦被避免了,同时避免的还有以后的补丁和软件修正。结果是一个更为健壮和可维护的产品的按期发行,于是产品在经济上成功的可能性也就更大了。

使用传统方法管理的项目,陷于集成的无效性和实质设计问题的发现过晚,把总资源消耗的40%花在集成和测试活动上,而这些努力大多带来的是过量的碎片和返工。采用迭代过程和指导式领导的现代项目发行一个产品,上述活动只消耗了预算的25%。

我讨论了真正使用迭代开发精神管理的项目的四种成功模式。每个模式表现了一种平衡,它能够帮助团队掌控制做产品和获得经济效益的路径:

用户需要与设计资产间的平衡
创造性过程的自由性与生产过程的严格性间的平衡
产品进度与实验性的识别背离的平衡
抽象观点与通过测试进行的切实评估间的平衡

根据我的经验,前例中的传统项目外观仍然是普遍的,是我们今天见到的一半以上项目的特征。尽管这些项目中的多数使用传统的工程管理方法,有一些声称使用了现代迭代开发。但是,由于不采用指导式领导,它们没能成功取得预期的商业结果。也许今天的项目有四分之一采用了现代模式,但只有八分之一能够在目标外观上进行操作。正是从这些不固定的外观和成功的结果上我观察出了本文所讨论的风格的一致使用问题。

和建造一座桥比起来,软件项目管理真的更像管理一部电影作品吗?也许不是这样,特别是在产品的后几个阶段。但是我希望这种类比能使读者从不同的参考中来审视软件项目管理技术。这些模式不是新的。它们在很多组织,以各种不同的程度,在广泛领域内经过了实践(尽管不太经常)。如果你深入研究在实践中使用这些模式,你会发现它们都着眼于处理管理上的人与团队工作的方面,很少带有科学、工程或是制造业的偏见。我认为采用指导式管理的组织更容易取得经济上的成功——甚至可能一鸣惊人。


版权所有:UML软件工程组织