软件工程新方法学.docx
- 文档编号:9007384
- 上传时间:2023-02-02
- 格式:DOCX
- 页数:22
- 大小:35.11KB
软件工程新方法学.docx
《软件工程新方法学.docx》由会员分享,可在线阅读,更多相关《软件工程新方法学.docx(22页珍藏版)》请在冰豆网上搜索。
软件工程新方法学
软件工程新方法学
版权申明:
本文的翻译没有获得作者的授权,所以这篇译文仅作为学习使用。
禁止任何人转载此文获作为商业用途,如果有任何人认为这篇文章侵犯了你的权利,请来信告诉我们。
MartinFowler
在过去几年中,敏捷方法(agilemethodologies)(也被称为轻量级方法,lightweightmethodology)正在迅速升温。
它能够有效的解决软件开发中的官僚作风,让大家的注意力重新集中在软件的秀丽风景中。
这篇文章展示了轻型方法产生的原因,当然不是讨论它们的重量,而是他们那符合自然规律和以人为先的特性。
同时文章还给出了学习过程中的一些参考意见和一些影响你在轻型方法这条康庄大道上继续前进的因素。
(译者注:
agilemethodology,agile在字典中的原意为敏捷的,轻快的,灵活的。
但是我始终没有找到有比较权威的翻译,原先我打算根据它的另一个称谓;轻量级方法,将它翻译成轻型方法,但是在查资料中发现了管理学中也存在这个词同类词:
AgileManufacturing,翻译为敏捷制造,所以我也把这个词同样翻译成敏捷方法。
如果读者觉得有更好的翻译,请mail给我。
axing@)
从无,到纪念碑的,到敏捷的
可预测型VS适应型的
设计和建构的分离
需求的不可预测性
可预测是无法做到的吗?
控制一个不可预测的过程
适应型客户
人是第一位的
同一的编程机器
程序员--有责任感的专业人员
面向过程的人员管理
业务领导者的角色
自适应型过程
方法
XP
Cockburn的CrystalFamily
开放源码
Highsmith的适应型软件开发
SCRUM
DSDM
敏捷软件开发的宣言
RUP是一个敏捷方法吗?
其他资源
你应该使用敏捷方法吗?
从无,到纪念碑的,到敏捷的
大多数的软件开发都是一个混乱、无序的过程,人们将之戏称为“codeandfix”。
软件的开发毫无计划性可言,系统设计就是把许多短期决定揉在一起。
这在小的系统中可以胜任,可随着系统的增长,往系统中加入新的功能就变成一件极端困难的事情。
此外,bug越来越普遍,修正也越来越困难。
这样系统的一个典型现象是在系统完成之后会经历一个相当长的测试时期。
测试和除错完全不可预见,如此之长的测试期严重破坏了开发进度。
我们的这种开发软件的风格存在了很长的一段时间,但是我们也花了很长的时间来研究替代方案:
方法学。
方法学把严格规范的过程用于软件开发,使软件开发更具可预见性、更有效率。
他们遵循规则,制定计划,细分过程来保证软件开发。
这种方法学也经历了很长的发展时间。
它们并不十分成功,也不致力于大众化。
这些方法学的最时常发生的批评是官僚。
为了遵循方法学的准则做的大量的无用功使得开发的步调缓慢。
因此他们时常被称为重方法学(heavymethodologies),或使用JimHighsmith的话:
丰碑般的方法学。
(译者注:
段落小标题的丰碑由此而来)
在这些方法学的带动下,近几年出现了一群新的方法学。
在一段时间内,它们被称为轻量级方法(lightweightmethodologies),但是现在普遍称之为敏捷方法。
人们希望敏捷方法能够有效解决丰碑式方法的官僚问题。
这些新的方法尝试着在毫无过程和太多过程之间找到一个有效的平衡点,只提供必要的过程以得到一个合理的结果。
这样的结果是敏捷方法在某些方面和重量级方法有显著的不同。
最大的不同是敏捷方法不是文档驱动的,通常一件给定的工作只需要很少的文档。
在很多方面,它倒是以代码驱动的:
规则,最重要的文档是源代码。
不过我不认为这是敏捷方法的重点所在。
较少的文档只是两种方法之间更深层次的不同点的一个症状:
1、敏捷方法是适应型的,而并非可预测型的。
重方法倾向于为软件开发制定一个包容了大量细节、时间跨度极长的庞大计划,如果万事都不变,这个计划将会执行得非常好。
所以它们必然要尽力阻止变化得发生。
敏捷方法则不同,它拥抱变化。
他们总是去适应变化,利用变化来发展,甚至改变自己
2、敏捷方法是以人为本而不是以过程为本的。
他们建立起一种观念:
工作应该能够发挥人的特性,而不是去限制它,强调软件开发过程应该是一个有趣的过程。
在下列各段中,我将更详细地研究这些不同之处,你能了解到一个发挥合适的、以人为本的方法是什么样的,它的优缺点。
不论你是软件的开发者还是使用者,你都应该使用这种方法。
可预测型VS适应型的
设计和建构的分离
方法学的灵感来自语工程学的工程规范,诸如土木工程和机械工程。
这种规范强调在实际建造之间做充分的计划。
这样工程师将会用一系列的图纸来精确描述该建造些什么,以及如何组织它们。
同时,根据图纸作出许多设计决定,比如该如何处理一座桥的负荷。
设计好的图纸随即被移交到另一个团队,通常是一家不同的公司,让他们来负责构建。
一般要假定构建程序要严格的遵循图纸。
在实际中负责构建的人会遇到一些问题,但通常都是些小问题。
因为图纸规定了各个模块是何如组装在一起的,这些模块在具体构建计划中扮演了一个基础的角色。
这样的一个计划能够计算出需要哪些工作,各项工作之间的关系如何。
这就需要考虑可预测的进度表和建造预算。
同时图纸也详细地说明了哪些构建者应嘎如何完成他们的工作。
这样,构建工作就不太需要那些智力型的工作者,只需要那些劳作型的工作者。
我们来看看设计和构建的根本不同。
设计很难预测,而且需要有创造力的人,而那些人往往都很昂贵,而构建则比较容易预测。
只要设计工作完成,我们就能开始计划构建。
一旦有了构建计划,就能够开始构建,而这个过程是容易预测的。
在土木工程中,构建阶段花费时间和金钱远远超过设计和计划。
所以众多的方法学看起来就像这样:
我们想要一种可预测的进度表来帮助组织、使用那些技术欠佳的人。
为了做到这一点我们需要把设计和构建阶段分开。
因此我们需要计算如何做设计和计划以保证构建的顺利进行。
而计划应该采用何种形式呢?
对於多数人来,就是诸如UML之类的设计记号法所要扮演的角色。
如果我们的所有重要决定都使用UML,我们就能够建立一个建构计划并且把这些设计交给编码人员来开发,完成构建活动。
但是这里有一些至关重要的问题。
你的设计能够保证把编码组织起来,完成一个完整的构建活动吗?
即使这点你能做到,那么,你的构建过程在时间和金钱上的花销真的大到那种不得不采用这种方法的程度了吗?
这些怎能不引人深思呢。
首先是把像UML那样的设计图移交给程序员来实现是一件极为困难的事情。
问题的关键在于那种设计看上去不错,可你打算编程来实现它的时候就出现了问题。
土木工程师使用的模型建立在多年实践的基础上,它们用土木工程的专用语言来描述。
而且主要的问题在于,通常这种设计需要符合数学原理。
而我们对UML之类的图表唯一能做的就是同级检查。
虽然这是有帮助的,但还是往往会忽略一些错误,这些错误只有到编码和测试阶段才能被发现。
即使是熟练的设计者,例如我觉得我就是一位,在把设计转为软件的时候,也会被其中的问题吓一大跳。
另外的一个问题是费用的不可比。
当你建立一座桥的时候,设计的费用约占全部工作量的10%,其余的工作量都在建构阶段。
在软件中编码的时间消耗则小得多。
(McConnell建议在一个大的项目中,编码和单元测试的开销占整个项目开销的15%,这个比例和建桥的比例刚好是相反的。
即使你把所有的测试也算在构建阶段中,设计仍然占了50%的工作量)。
这就引起了一个至关重要的问题,因为通常我们都是把软件设计看做是工程学的一个分支的。
种种问题使得JackReeves提出,事实上源代码就是一份设计文档,而构建阶段实际上是编译器和连接器的使用。
的确,你视为建构阶段的任何事都能而且也应该被自动化。
这就引出了一些重要的结论:
在软件中:
建构阶段是廉价而自由的。
在软件中所有的努力都是在设计,这需要那些富有创造力而且聪明的人。
有创造力的过程可不是那么容易计划的,而且具有可预测性也是一个不可能达成的目标。
我们用传统的工程来隐喻设计软件应该非常小心。
它们是不同的类型的活动,需要的过程也是不同的。
需求的不可预测性
在我经历的每一个有问题的项目中,我听到的总是同样的声音。
开发人员跑过来对我说:
“这个项目之所以有问题,是因为需求总是在变。
”再也没有比这更令人惊讶的了。
在商业软件开发领域,需求变化是很正常的,问题是我们该怎样对待它。
一条路是对把需求变更视为拙劣的需求工程所造成的恶果。
需求工程要求你在开发软件之前对整个系统的需求有完整的了解,让客户确任需求,并严格按照需求设计程序,其中,不允许需求的变更。
这样就产生了一个问题,想要了解需求的一些信息是件困难的事,而要求开发组织提供需求的具体费用信息更是难于登天。
如果你想要给你的车加上天窗,可是卖汽车的那家伙根本说不出花10块钱的天窗和要10000块钱的那种有什么区别。
对这两种费用完全没有概念,试问,你能决定选用那种天窗吗。
相信大多数人都不会作出决定的。
这种预算往往因为某些理由而难以做到,一个原因是软件开发是一项设计活动,难以计划和制定费用。
另一个原因是基本的要素变化很大。
还有一个原因是需求过于依赖于参与的个人,而个人是难于编制预算和量化的。
软件的无形价值的特性也加大了难度。
除非投入使用,否则很难估算出软件的功能有什么价值。
只有当你使用软件的早期版本时,你才能了解哪些功能是有价值,哪些是没有价值的。
具有讽刺意味的是,这使得人们希望需求是可以变化的。
毕竟,软件被称为“软”件。
需求一旦发生变化,软件也要能发生变化。
这往往要求开发者费尽心机来说服客户固定需求。
更糟的是,如果那个客户刚好涉猎过软件领域,说服他们可就更不是件容易的事了,因为他们知道那玩艺儿是很容易改变的。
即使你可以搞定你的客户,拿出一份准确、稳定的需求,可你还是注定失败。
当今商业活动赖以生存的经济瞬息万变,要求软件的功能能够迅速改变。
什么才是好的需求集呢,决不是只适用6个月的那种。
即使客户能固定他们的需求,现实的商业世界也不会为了他们而停止。
而在商业领域中,很多改变是完全不可预知的:
否则那个人不是在说谎,就是已经在股票市场赚了数十亿了。
软件开发中的其他阶段都必须依赖于需求。
如果你不能够拿出一份稳定的需求,你就不能得到一份可预期的计划。
可预测是无法做到的吗?
大体上,这是做不到的。
也有一些软件开发是可以被预测的。
例如美国航空航天总署的太空船软件团体组织就是这方面的一个典型例子。
它需要大量的仪式,足够多的时间,庞大的团队和稳定的需求。
所以能够制定出太空船那样的计划。
然而我不认为这么多商用软件适合这种方法。
为此你需要一个完全不同的过程。
一个极大的风险在于你总认为你可以遵循一个可预测的过程,但实际上,你不行。
使用方法进行工作的人们并不能很好的识别边界条件:
方法从适合到不适合的交界之处。
决大多数的方法学家希望他们的方法学能被每个人使用,因此他们不了解也不宣传他们的边界条件。
这就误导了人么,在错误的环境中使用一种方法,例如,在一种不可预测的情形中使用一种可预测的方法学。
然而总有种强烈的诱惑驱动你去那样做。
可预测性是一项极为宝贵的财富,非常令人动心。
然而如果你相信你可以预见到什么,但是实际上你做不到。
这就导致人们过早建立计划的情形,然后因为处理不当致使计划失控的情形。
你可以看见计划和现实慢慢脱离的。
很长的一段时间里,你仍认为计划仍然有效。
但是当脱离越来越明显,计划最终失败。
这该是多么的痛苦。
所以不论你是否处在这么一个可预测的环境中,你都不能使用可预测的方法。
这是很痛苦的事情。
意谓着为了控制项目,为了整体的客户关系而制作的大量模型,而这些根本不对。
可预测性的好处确实很大,但要做到却很困难。
象这麽多问题,其中最难的部份却是了解问题是否存在。
然而去掉可预测性并不意谓你回到无法控制的混乱局面。
实际上你需要一个能控制不可预测性的流程。
这就是合适性的本意。
控制一个不可预测的过程
那么我们该如何在一个不可预知的世界中控制我们自己?
最重要的,而且困难的是要如何正确地知道我们处在那个位置上。
我们需要一种反馈机制,它可以每隔一段时间就告诉我们准确的位置。
反馈的关键是迭代开发。
这不是一个新的想法。
迭代开发以前有很多的名称:
增量模型,改良模型,阶段模型,螺旋模型...。
迭代开发的关键在于把最终的系统划分为多个可工作的版本,每一个版本都实现了功能的一个子集。
这些可工作系统都实现了全部功能的一小部分,但都完全符合系统最终的要求。
他们都应该被完全整合并通过的小心的测试,做为最终版本交付。
一个经过测试、整合的系统无疑给那些计划注入了一针现实的强心针,再没有什么比这更好的了。
文档能隐藏几乎所有的缺点。
未经测试的代码同样能隐藏许多缺点。
但是当人们真正坐在一个系统之前并用它来工作的时候,缺点就显现出来了:
不论是bug还是曲解的需求。
迭代开发在可预测的过程中也样有效。
但它是是适应性过程的核心思想,因为一个适应性过程需要处理功能需求上的变化。
这使得迭代开发往往呈现出远期计划不固定,稳定的计划只是每次迭代的短期计划的风格。
迭代开发在每一次的迭代中提供了一个坚实的基础以保证计划的制定。
另一个主要问题是一次迭代需要多长的时间。
这个问题的答案因人而异。
XP建议一次迭代差不多需要在一到三个星期之间。
SCRUM建议议一月的长度。
Crystal则更远一些。
整体的趋势是使每一次迭代都保持在你能够对付的时间范围之内。
这种机制提供了频繁的反馈,因此你更好的知道你在哪里。
适应型客户
这种适应型的过程需要和客户建立一种全新的关系,而不是原先那样,尤其是开发部分由另一个公司负责的时候。
当你雇请一个单独的公司做软件开发的时候,决大多数的客户会较喜欢一份固定价格的合同。
告诉开发者他们想要的,要求竞标,接受竞标,然後负责是在发展组织上开发软件。
一份固定价格的合同要求稳定的需求,因此也就需要一个可预测型的过程。
适应型和不稳定的需求暗示你不能采用固定价格的平常观念来处理问题。
对一个适应型过程建立一个固定价格机制的尝试在经历一个痛苦的摸索后宣布失败。
最糟糕的是这种做法深深伤害了客户,同时也伤害了软件公司。
除非特别需要,用户不一定想要那些软件,前提是不用这些软件也不会损害生意。
所以即使他们什么都没有付给开发公司,他们还是失去了很多。
的确,他们失去的价值超过了软件的费用。
(如果那个软件没什么价值,我为什么要付费呢?
)
所以在可预测型过程无法使用的条件下双方签署一份固定价格的合同是及其危险的。
这意谓客户必须不同的工作。
在一个适应型过程中客户对软件开发过程会把握的更好。
在每次迭代,双方都必须检查进度以决定是否改变软件开发的方向。
这有利于和软件开发者建立一种更密切的关系,真正的生意伙伴。
这种程度的契约关系并不是每个客户组织和每个软件开发者都必须达到的,但是它能够使一个适应型过程很好的工作。
客户的主要利益比软件开发的回应要重要多了。
一个可以使用的,虽然可能很小的系统可以尽量早的投入使用。
然后客户会根据生意的变化来改变系统的性能,而且能够从现实中存在的系统中学习。
人是第一位的
适应型过程的执行可不是一件容易的事情。
它特别需要一支高效的开发人员团队。
这个团队的每一个成员都应该具有高素质,能够相互配合。
这里有个有意思的合作优势:
不仅仅是适应型过程需要一个强有力的团队,大多数的开发人员也原意加入到适应型过程中来。
同一的编程机器
传统方法的目标是建立起一个过程,把参与者分成多个可以替换的角色。
在这样一个过程中,参与者在你眼中都是各种各样的资源以供使用。
你有一个分析员,几个编码人员,几个测试人员,一个项目经理。
至于每个人是不重要的,角色才是重要的。
这样你在计划一个项目的时候考虑的不是你需要哪一个分析员,或是哪几个测试人员,你要考虑的只是你有多少的人可以用,你的计划所需要的资源。
但这样就会引出一个关键问题:
项目的参与者真的只是一些可以替换的角色吗?
敏捷方法的一个关键特点就是推翻了这项假设。
AlistairCockburn就是一个强烈反对把人看做资源的这种做法的人。
在他的论文《CharacterizingPeopleasNon-Linear,First-OrderComponentsinSoftwareDevelopment中,提出一个观点,可预测型过程需要它的各个组成部分也必须是可以预测的。
然而人从来就不属于可以预测的部分。
他还进一步研究了软件项目,得出的结论是,人是软件开发中最重要的要素之一。
尽管Cockburn是如此尽力的宣传这种软件开发须以人为中心的思想,可是这种以人为先的思想却还只是软件领域那群思想家笔下的共同主题。
造成这种现象的最常见的一个问题就是旧有的方法排斥这种以人为先的的思想。
这就产生恶性循环:
因为你希望你的开发人员都能成为统一标准的编程机器,你就不会把他们视为一个个有个性的人。
这样,士气和生产力就下降了。
你的优秀的员工会离开你,找个更好的地方,而你那希望大家都成为同一编程机器的想法最终是失败了。
要转变观念需要很大的决心,而且需要许许多多的决策来支持推动。
视人为资源的观念已经深入人心了,其根源甚至可以追溯到FrederickTaylor的科学的管理方法的影响(译者注:
FrederickTaylor提出的管理思想是针对大工业时代的生产的)。
在一个工厂中,FrederickTaylor的方法或许用效。
但是对于有着非凡的创造力的计算机专家而言,这种方法就未必有用了。
(实际上,现代的工厂也已经淘汰了FrederickTaylor的方法了)
程序员--有责任感的专业人员
Taylorist理论最关键的一点是他认为那些工人并不会主动改进工作,从而更好的完成工作。
在一个工厂里,这个理论也许成立。
原因有二:
一是工厂中有相当一部分的工人都不是那种绝顶聪明,又富有创造力的人;二是管理者和工人间的关系很紧张,因为工人的酬劳越低,相应工厂所有人的收入就越高。
近来的历史经验表明,这个理论在软件开发中是站不住脚的。
受到软件行业的耀眼光环和潜在高收入的吸引,有越来越多的聪明能干的人投身到这个行业中。
(我也是其中的一位,离开电气工程行业进入软件行业。
)例如现在的股票期权也是为了让程序员的发展能够和公司发展相一致。
如果你想要使用最优秀的员工并能够留住他们。
你就必须认识到他们都是真正的专家,而且,他们都是最棒的,完全能够完成你的技术活儿。
Taylorist的那种把计划部门单独出来的做法只有在计划者比那些工人更优秀、更能胜任工作的条件下才成立。
如果你确实很聪明,把你的聪明才智放在如何激励你的属下上吧,而不是去阻碍他们。
面向过程的人员管理
敏捷方法中以人为本有很多种的实现方法。
这些方法的效果各不相同,而且其中一些方法之间也无法共通。
一个是改被迫接受为主动接受。
常常管理者都会给程序员强行施加一些任务,通常开发人员都对这种任务很敌视,如果这项任务需要占用大量的时间使得程序员不得不从手头的任务中挤出时间的话,这种敌视的程度还会加剧。
改被迫接受为主动接受需要开发人员主动承担,而且需要整个团队的积极参与。
这就有了一个有趣的结果,只有开发人员自己有权利选择开始一个适应型过程。
正在XP中已经做到了,当然还有许多的准则来保障。
而这也是Crystal的长处:
只有很少的准则,却能够有效的完成任务。
另一个观点是开发人员必须做出所有的技术决策。
XP就体现了这个观点的核心思想:
它规定在计划阶段,只有开发人员才能预估出任务需要的时间。
这样,技术领导者的身份有了很大的转变,众多的开发人员成了管理者。
这种方法需要一个项目中开发人员和管理者是平等的,有着同等的地位,同样的责任。
注意,我说的平等指的是仍然存在管理者这个职位,但可能是由那些资深的开发人员来担任。
这样做的一个很重要的理由是计算机产业中技术以极高的速度发展。
短短几年,技术就可能已经过时了。
这个产业的技术能力和其它产业简直不可同日而语。
技术人员必须意识到,进入管理领域将会使他们的技术能力迅速萎缩。
那些资深的开发人员也必须认识到他们的技能也会很快的消失,你必须相信、依靠其他的开发人员。
业务领导者的角色
技术人员是没有办法独自完成整个开发过程的。
他们需要业务需求上的指导。
这就引出了适应型过程中的另一个重要的概念:
开发人员需要和业务专家保持非常紧密的接触。
大部分的项目中都准备了业务的角色,一个敏捷团队决不仅仅只是和客户做短暂的交流,他们会和业务领域的专家不断的交流。
而且这种交流并不只是停留在管理层面上,而是深入到每个开发人员,每一个的细节。
开发人员和业务领域专家一样都遵循一定的准则。
这样的主要是因为适应型的方法强调本性。
既然适应型方法假定事务总是迅速变化的,你就必须不断的和业务专家保持交流以保证改变。
恐怕对开发人员最大的打击就是看到自己的努力成果付诸东流。
所以,重点在于,必须要有一个高素质的业务专家,开发人员能够从他那里的到帮助。
自适应型过程
迄今为止,我们已经讨论了在一个适应型过程中适应性是如何迎合快速改变的用户需求的。
但这里还有个需要注意的问题:
过程自身也是在不断变化的。
一个项目目前用的一个过程和一年后的项目用的过程肯定不同。
随着时间流逝,一个团队会发现怎样才能更好的工作,从而相应改变过程。
自适应型过程的第一步就是阶段性的复审你的过程。
你可以在每一次迭代结束的时候做这件工作。
开一个短会,问自己几个问题:
(精选自NormKerth)
我们什么地方做的好?
我们学到了些什么?
我们怎么才能做的更好?
我们还有什么疑问?
这些问题可以帮助你在下一次迭代中改进你的过程。
每个过程开始的时候都带有疑问,然后在过程中解决疑问,改进过程。
这样做可以使过程运作的更好。
如果这种自适应发生在一个项目中,它对于整个组织有更显著的作用。
为了加深自适应的过程,我建议每个团队每个阶段召开正式的审查会,建立主要的项目里程碑,举办定期的项目回顾会议(outlinedbyNormKerth)。
这种回顾会议包括一个二到三天一次的会议和一个训练机制。
这不仅使团队有了学习的机会,也使整个组织有了学习的机会。
这种自适应的结果是你不可能找到一个简单的合作方法。
实际上每个团队都不能够仅限于自身的过程,而应该积极的改变过程以配合整个项目的进行。
尽管有那些成文的过程和项目的经验可以作为参考,开发人员还是有责任不断的改进过程以完成手头的工作。
这种自适应性在ASD和Crystal方法中尤为强调。
XP方法严格的规定表面上看似乎是排斥这种自适应性,但实际上XP方法是鼓励人们去改变过程的。
XP方法的最大的不同在于,它建议这种改变在实际作用于过程之前需要经历多个的迭代阶段。
而审查并不是XP方法强调的,也不是XP过程的一部分。
尽管有许多人建议XP的关键实践应该加入审查这个环节
方法
目前已经有几种方法能够体现敏捷的思想了。
虽然这些方法都具有很多共通的特性,但是它们还是有很多的不同点。
因为这篇文章只是起提纲挈领的作用,我没有办法一一指出这些不同点,不过我至少会指出一些重要之处。
我也没办法谈论这些方法的精髓之处。
尽管我在XP方法上花费了很多的心血,对于RUP我也略有心得。
不过对于其它的方法来说,我就显得有些无能为力了。
XP(eXtremeProgramming)
在所有的敏捷方法中,XP方法是最受瞩目的一种。
一个很大的原因是他的发明者--KentBeck的非比寻常的耀眼光芒。
KentBeck做了大量的工作来推
- 配套讲稿:
如PPT文件的首页显示word图标,表示该PPT已包含配套word讲稿。双击word图标可打开word文档。
- 特殊限制:
部分文档作品中含有的国旗、国徽等图片,仅作为作品整体效果示例展示,禁止商用。设计者仅对作品中独创性部分享有著作权。
- 关 键 词:
- 软件工程 新方法
![提示](https://static.bdocx.com/images/bang_tan.gif)