当前位置: 首页 > 编程日记 > 正文

怎么成为优秀的软件模型设计者?

作者:Scott Ambler著,乐林峰 译
本文选自:www.umlchina.com
2002年03月25日

我们期待自己成为一个优秀的软件模型设计者,但是,要怎样做,又从哪里开始呢?

将下列原则应用到你的软件工程中,你会获得立杆见影的成果。

1. 人远比技术重要

你开发软件是为了供别人使用,没有人使用的软件只是没有意义的数据的集合而已。许多在软件方面很有成就的行家在他们事业的初期却表现平平,因为他们那时侯将主要精力都集中在技术上。显然,构件(components),EJB(Enterprise Java Beans)和代理(agent)是很有趣的东西。但是对于用户来说,如果你设计的软件很难使用或者不能满足他们的需求,后台用再好的技术也于事无补。多花点时间到软件需求和设计一个使用户能很容易理解的界面上。

2. 理解你要实现的东西

好的软件设计人员把大多数时间花费在建立系统模型上,偶尔写一些源代码,但那只不过是为了验证设计过程中所遇到的问题。这将使他们的设计方案更加可行。

3. 谦虚是必须的品格

你不可能知道一切,你甚至要很努力才能获得足够用的知识。软件开发是一项复杂而艰巨的工作,因为软件开发所用到的工具和技术是在不断更新的。而且,一个人也不可能了解软件开发的所有过程。在日常生活中你每天接触到的新鲜事物可能不会太多。但是对于从事软件开发的人来说,每天可以学习很多新东西(如果愿意的话)。

4. 需求就是需求

如果你没有任何需求,你就不要动手开发任何软件。成功的软件取决于时间(在用户要求的时间内完成)、预算和是否满足用户的需求。如果你不能确切知道用户需要的是什么,或者软件的需求定义,那么你的工程注定会失败。

5. 需求其实很少改变,改变的是你对需求的理解

Object ToolSmiths公司(www.objecttoolsmiths.com)的Doug Smith常喜欢说:“分析是一门科学,设计是一门艺术”。他的意思是说在众多的“正确”分析模型中只存在一个最“正确”分析模型可以完全满足解决某个具体问题的需要(我理解的意思是需求分析需要一丝不苟、精确的完成,而设计的时候反而可以发挥创造力和想象力 - 译者注)。

如果需求经常改动,很可能是你没有作好需求分析,并不是需求真的改变了。

你可以抱怨用户不能告诉你他们想得到什么,但是不要忘记,收集需求信息是你工作。

你可以说是新来的开发人员把事情搞得一团糟,但是,你应该确定在工程的第一天就告诉他们应该做什么和怎样去做。

如果你觉得公司不让你与用户充分接触,那只能说明公司的管理层并不是真正支持你的项目。

你可以抱怨公司有关软件工程的管理制度不合理,但你必须了解大多同行公司是怎么做的。

你可以借口说你们的竞争对手的成功是因为他们有了一个新的理念,但是为什么你没先想到呢?

需求真正改变的情况很少,但是没有做好需求分析工作的理由却很多。

6. 经常阅读

在这个每日都在发生变化的产业中,你不可能在已取得的成就上陶醉太久。

每个月至少读2、3本专业杂志或者1本专业书籍。保持不落伍需要付出很多的时间和金钱,但会使你成为一个很有实力的竞争者。

7. 降低软件模块间的耦合度

高耦合度的系统是很难维护的。一处的修改引起另一处甚至更多处的变动。

你可以通过以下方法降低程序的耦合度:隐藏实现细节,强制构件接口定义,不使用公用数据结构,不让应用程序直接操作数据库(我的经验法则是:当应用程序员在写SQL代码的时候,你的程序的耦合度就已经很高了)。

耦合度低的软件可以很容易被重用、维护和扩充。

8. 提高软件的内聚性

如果一个软件的模块只实现一个功能,那么该模块具有高内聚性。高内聚性的软件更容易维护和改进。

判断一个模块是否有高的内聚性,看一看你是否能够用一个简单的句子描述它的功能就行了。如果你用了一段话或者你需要使用类似“和”、“或”等连词,则说明你需要将该模块细化。

只有高内聚性的模块才可能被重用。

9. 考虑软件的移植性

移植是软件开发中一项具体而又实际的工作,不要相信某些软件工具的广告宣传(比如java 的宣传口号write once run many ? 译者注)。

即使仅仅对软件进行常规升级,也要把这看得和向另一个操作系统或数据库移植一样重要。

记得从16位Windows移植到32位windows的“乐趣”吗 ?当你使用了某个操作系统的特性,如它的进程间通信(IPC)策略,或用某数据库专有语言写了存储过程。你的软件和那个特定的产品结合度就已经很高了。

好的软件设计者把那些特有的实现细节打包隐藏起来,所以,当那些特性该变的时候,你的仅仅需要更新那个包就可以了。

10. 接受变化

这是一句老话了:唯一不变的只有变化。

你应该将所有系统将可能发生的变化以及潜在需求记录下来,以便将来能够实现(参见“Architecting for Change”,Thinking Objectively, May 1999)

通过在建模期间考虑这些假设的情况,你就有可能开发出足够强壮且容易维护的软件。设计强壮的软件是你最基本的目标。

11. 不要低估对软件规模的需求

Internet 带给我们的最大的教训是你必须在软件开发的最初阶段就考虑软件规模的可扩充性。

今天只有100人的部门使用的应用程序,明天可能会被有好几万人的组织使用,下月,通过因特网可能会有几百万人使用它。

在软件设计的初期,根据在用例模型中定义的必须支持的基本事务处理,确定软件的基本功能。然后,在建造系统的时候再逐步加入比较常用的功能。

在设计的开始考虑软件的规模需求,避免在用户群突然增大的情况下,重写软件。

12. 性能仅仅是很多设计因素之一

关注软件设计中的一个重要因素--性能,这好象也是用户最关心的事情。一个性能不佳的软件将不可避免被重写。

但是你的设计还必须具有可靠性,可用性,便携性和可扩展性。你应该在工程开始就应该定义并区分好这些因素,以便在工作中恰当使用。性能可以是,也可以不是优先级最高的因素,我的观点是,给每个设计因素应有的考虑。

13. 管理接口

“UML User Guide”(Grady Booch,Ivar Jacobson和Jim Rumbaugh ,Addison Wesley, 1999)中指出,你应该在开发阶段的早期就定义软件模块之间的接口。

这有助于你的开发人员全面理解软件的设计结构并取得一致意见,让各模块开发小组相对独立的工作。一旦模块的接口确定之后,模块怎样实现就不是很重要了。

从根本上说,如果你不能够定义你的模块“从外部看上去会是什么样子”,你肯定也不清楚模块内要实现什么。

14. 走近路需要更长的时间

在软件开发中没有捷径可以走。

缩短你的在需求分析上花的时间,结果只能是开发出来的软件不能满足用户的需求,必须被重写。

在软件建模上每节省一周,在将来的编码阶段可能会多花几周时间,因为你在全面思考之前就动手写程序。

你为了节省一天的测试时间而漏掉了一个bug,在将来的维护阶段,可能需要花几周甚至几个月的时间去修复。与其如此,还不如重新安排一下项目计划。

避免走捷径,只做一次但要做对(do it once by doing it right)。

15. 别信赖任何人

产品和服务销售公司不是你的朋友,你的大部分员工和高层管理人员也不是。

大部分产品供应商希望把你牢牢绑在他们的产品上,可能是操作系统,数据库或者某个开发工具。

大部分的顾问和承包商只关心你的钱并不是你的工程(停止向他们付款,看一看他们会在周围呆多长时间)。

大部分程序员认为他们自己比其他人更优秀,他们可能抛弃你设计的模型而用自己认为更好的。

只有良好的沟通才能解决这些问题。

要明确的是,不要只依靠一家产品或服务提供商,即使你的公司(或组织)已经在建模、文档和过程等方面向那个公司投入了很多钱。

16. 证明你的设计在实践中可行

在设计的时候应当先建立一个技术原型, 或者称为“端到端”原型。以证明你的设计是能够工作的。

你应该在开发工作的早期做这些事情,因为,如果软件的设计方案是不可行的,在编码实现阶段无论采取什么措施都于事无补。技术原型将证明你的设计的可行性,从而,你的设计将更容易获得支持。

17. 应用已知的模式

目前,我们有大量现成的分析和设计模式以及问题的解决方案可以使用。

一般来说,好的模型设计和开发人员,都会避免重新设计已经成熟的并被广泛应用的东西。http://www.ambysoft.com/processPatternsPage.html收藏了许多开发模式的信息。

18. 研究每个模型的长处和弱点

目前有很多种类的模型可以使用,如下图所示。用例捕获的是系统行为需求,数据模型则描述支持一个系统运行所需要的数据构成。你可能会试图在用例中加入实际数据描述,但是,这对开发者不是非常有用。同样,数据模型对描述软件需求来说是无用的。每个模型在你建模过程中有其相应的位置,但是,你需要明白在什么地方,什么时候使用它们。

19. 在现有任务中应用多个模型

当你收集需求的时候,考虑使用用例模型,用户界面模型和领域级的类模型。

当你设计软件的时候,应该考虑制作类模型,顺序图、状态图、协作图和最终的软件实际物理模型。

程序设计人员应该慢慢意识到,仅仅使用一个模型而实现的软件要么不能够很好地满足用户的需求,要么很难扩展。

20. 教育你的听众

你花了很大力气建立一个很成熟的系统模型,而你的听众却不能理解它们,甚至更糟-连为什么要先建立模型都不知道。那么你的工作是毫无意义的。

教给你开发人员基本的建模知识;否则,他们会只看看你画的漂亮图表,然后继续编写不规范的程序。

另外, 你还需要告诉你的用户一些需求建模的基础知识。给他们解释你的用例(uses case)和用户界面模型,以使他们能够明白你要表达地东西。当每个人都能使用一个通用的设计语言的时候(比如UML-译者注),你的团队才能实现真正的合作。

21. 带工具的傻瓜还是傻瓜

你给我CAD/CAM工具,请我设计一座桥。但是,如果那座桥建成的话,我肯定不想当第一个从桥上过的人,因为我对建筑一窍不通。

使用一个很优秀的CASE工具并不能使你成为一个建模专家,只能使你成为一个优秀CASE工具的使用者。成为一个优秀的建模专家需要多年的积累,不会是一周针对某个价值几千美元工具的培训。一个优秀的CASE工具是很重要,但你必须学习使用它,并能够使用它设计它支持的模型。

22. 理解完整的过程

好的设计人员应该理解整个软件过程,尽管他们可能不是精通全部实现细节。

软件开发是一个很复杂的过程,还记得《object-oriented software process》第36页的内容吗?除了编程、建模、测试等你擅长工作外,还有很多工作要做。

好的设计者需要考虑全局。必须从长远考虑如何使软件满足用户需要,如何提供维护和技术支持等。

23. 常做测试,早做测试

如果测试对你的软件来说是无所谓的,那么你的软件多半也没什么必要被开发出来。

建立一个技术原型供技术评审使用,以检验你的软件模型。

在软件生命周期中,越晚发现的错误越难修改,修改成本越昂贵。尽可能早的做测试是很值得的。

24. 把你的工作归档

不值得归档的工作往往也不值得做。归档你的设想,以及根据设想做出的决定;归档软件模型中很重要但不很明显的部分。 给每个模型一些概要描述以使别人很快明白模型所表达的内容。

25. 技术会变,基本原理不会

如果有人说“使用某种开发语言、某个工具或某某技术,我们就不需要再做需求分析,建模,编码或测试”。不要相信,这只说明他还缺乏经验。抛开技术和人的因素,实际上软件开发的基本原理自20世纪70年代以来就没有改变过。你必须还定义需求,建模,编码,测试,配置,面对风险,发布产品,管理工作人员等等。

软件建模技术是需要多年的实际工作才能完全掌握的。好在你可以从我的建议开始,完善你们自己的软件开发经验。

以鸡汤开始,加入自己的蔬菜。然后,开始享受你自己的丰盛晚餐吧。

转载于:https://www.cnblogs.com/wfcfan/archive/2009/02/22/1395852.html

相关文章:

1012 The Best Rank

思路:读入全部的数据之后,按照四个cmp函数对数组进行排序,给每生的4个科目的排名赋值,读入要检验的id后使用strcmp对数组中的id进行遍历(幸好这里数组大小和要检验的数目乘积不超过4万),如果找到了相同id,调用写好的得…

SDWebImage使用——一个可管理远程图片加载的类库

SDWebImage托管在github上。https://github.com/rs/SDWebImage 这个类库提供一个UIImageView类别以支持加载来自网络的远程图片。具有缓存管理、异步下载、同一个URL下载次数控制和优化等特征。 将SDWebImage类库添加入工程时,一定注意需要添加MapKit.framework&…

EXECL使用技巧(转)

2007-03-18 09:07 一、求字符串中某字符出现的次数: 例:求A1单元格中字符"a"出现的次数: LEN(A1)-LEN(SUBSTITUTE(A1,"a","")) 二、如何在不同工作薄之间复制宏: 1、打开含有宏的工作薄&#xff0c…

微信小程序(canvas)画图保存到本地相册(wepy)

html标签部分 因为这个需要用户授权 所以需要使用button&#xff0c;画布使用的是canvas&#xff0c;这个可以参考小程序官方文档&#xff0c;代码如下 <button classbtn type"default" open-type"getUserInfo" tapexportImg>生成图片保存到本地&l…

1016 Phone Bills

目录 概述&#xff1a; 一些小的注意点 AC代码 概述&#xff1a; 这道题是我迄今做出来的最复杂的一道PAT了&#xff0c;该题被归类到排序专题下&#xff0c;其实还涉及到大量的字符串处理等别的我暂时也说不出的知识点。 排序函数我写了两个&#xff0c;1是cmp&#xff0…

C# GDI+ 简单绘图 (三) 仿浏览器截屏效果

感谢大家的支持,这几天从早忙到晚,一个字累呀!!!现在挺困的,但是又不习惯这么早睡觉,哎~~还是利用这个时间继续来写第三篇吧.  前两篇已经基本向大家介绍了绘图的基本知识.那么,我就用我们上两篇所学的,做几个例子&#xff0e;  我们先来做一个简单的----仿QQ截图,关于这个…

POJ 1236 Network of Schools(tarjan)

Network of SchoolsDescription A number of schools are connected to a computer network. Agreements have been developed among those schools: each school maintains a list of schools to which it distributes software (the “receiving schools”). Note that if B …

如何设置网页自动刷新(JSP,JS,HTML)

http://blog.163.com/ylx282006126/blog/static/59772717201111685917664/ 转载于:https://www.cnblogs.com/liuzhuqing/p/7480284.html

1084 Broken Keyboard

两个注意的点 1.本题被归到散列专题下&#xff0c;但是由于是逐字符地映射到整形&#xff0c;可以直接把布尔型哈希数组的大小设置为ASCII的数量128&#xff0c;然后直接将字符作为数组下标(如果是字符串&#xff0c;才需要自己写一个哈希函数&#xff0c;将字符串映射到整形&…

Android提示框与通知的使用

1.通知 Android 3.0以前使用的方法 1 NotificationManager nm (NotificationManager) getSystemService(NOTIFICATION_SERVICE); 2 Notification notification new Notification(R.drawable.dss, 3 "通知到了", Syste…

nginx安全日志分析脚本的编写

https://blog.csdn.net/nextdoor6/article/details/51914966

[转]笑死人的考试填空

高考完后又是中考&#xff0c;考题千奇百怪&#xff0c;答卷也五花八门。真佩服现在的学生啊&#xff0c;思维跳脱&#xff0c;天马行空&#xff0c;和我们那时候的循规蹈矩&#xff0c;差别太大了&#xff0c;呵呵。看一组语文试卷中的填空题&#xff1a;1.__________&#xf…

1033 旧键盘打字

1. 非常奇怪&#xff0c;明明都说了用下划线替代空格&#xff0c;但是用scanf读入的时候就会有1个测试点没通过&#xff0c;换成cin.getline就通过了 2.3种情况下对应的哈希表赋值为true。1是上来就赋值&#xff0c;2是对于大写字母把对应小写字母也赋值&#xff0c;这里注意直…

OLE 操作Excel 详解(转)

使用Excel模板进行报表的开发. 今年搞的Excel比较多&#xff0c;总结了一下&#xff0c;相信常用的操作包含的差不多了。 可以首先定义一个无内容的Excel报表模板文件. 通过Tcode SMW0 上传至SAP数据库中备用.(注: Web对象应该选择’WebRFC 应用程序的二进制数据’) 开发程序…

只需3分钟,就能轻松创建 一个SpreadJS的React项目

概述SpreadJS 纯前端表格控件 V11.2(SP2) 已经全面支持了 React 的拓展。接下来我们看下如何利用3分钟快速创建一个 SpreadJS 的 React 项目。1.新建React 项目&#xff08;耗时 1 Min&#xff09;直接运行&#xff1a;npx create-react-app react-spread-sheets还不清楚什么是…

1039 到底买不买

很典型的散列题&#xff0c;对于shop和eva有的珠子(即字符)&#xff0c;各开一个128长度的整形散列表计数&#xff0c;将字符作为下标读入。 然后从0~127进行遍历&#xff0c;看每个下标下两个散列表的数量&#xff0c;如果有shop<eva说明不买&#xff0c;但是遍历仍然要继…

什么是Linq

最近一直利用业余的时间来研究Linq&#xff0c;估计这样的文章在对于园子里很多牛人来说就有点小儿科了&#xff0c;前段时间写了一个Linq To Sql体验的小例子&#xff0c;感觉很简洁程序上操作体验不错&#xff0c;我写这些的文章目的是自我学习笔记的备用和查看&#xff0c;当…

OSS正式支持IPv6公测

背景 6月20日阿里云宣布全面支持IPv6&#xff0c; 随后阿里云开放对象存储OSS也逐步开始向用户公测。 公测步骤 正常使用IPv6服务&#xff0c;除了OSS端支持还需要客户端支持&#xff0c;我们做一些检查证明客户端具备访问 IPv6的能力&#xff0c;再使用OSS SDK或工具通过IPv6 …

C++中定义类的对象:用new和不用new的区别

Point p1; Point *p2new Point(); p1 由系统创建并释放&#xff0c;不用担心会出现内存泄露&#xff0c;但是生命期只有在本区域的大括号内&#xff0c;出了大括号就没用了。 P2 是指针&#xff0c;要自己释放&#xff0c;用不好很危险&#xff0c;用好了功能强大&#xff0c;…

1043 输出PATest

开一个长度为6的整型数组分别记录6个字符的数量&#xff0c;输出的时候条件是数组中至少存在一个不为零的元素 while(PATest[0]||PATest[1]||PATest[2]||PATest[3]||PATest[4]||PATest[5]){//当6个还有一个不为0 AC代码 #include<cstdio> #include<cmath> #inc…

[转载 js] YUI解决mouseout事件冒泡的办法

原文出处&#xff1a;http://design.alibaba-inc.com/?qnode/727&#xff1d;&#xff1d;&#xff1d;&#xff1d;&#xff1d;&#xff1d;&#xff1d;&#xff1d;&#xff1d;&#xff1d;&#xff1d;&#xff1d;&#xff1d;&#xff1d;&#xff1d;&#xff1d;&am…

adodb.RecordSet的属性和方法

为了更精确地跟踪数据&#xff0c;要用RecordSet组件创建包括数据的游标&#xff0c;游标就是储存在内存中的数据&#xff1a; rs Server.CreateObject("ADODB.RecordSet") rs.Open(sqlStr,conn,1,A) 注&#xff1a;A1表示读取数据&#xff1b;A3表示新增、改动或删…

给女友讲讲设计模式——适配器模式(JAVA实例)5

前言 有这样一个人&#xff0c;看到别人一个个开餐馆赚了好多钱&#xff0c;于是自己也很想在餐饮业这方面大展拳脚&#xff0c;他从别人那里学到了他们的理念&#xff0c;还学习到了他们真正开店的经验。不但如此&#xff0c;他还引进了除了吃饭意外其他的服务&#xff0c;例如…

1041 Be Unique

1.依旧是散列题&#xff0c;开一个整形的哈希数组bets[10010]来计数&#xff0c;最后数目为1的&#xff0c;也就是unique 2.注意&#xff0c;可能为1的不止一个&#xff0c;要输出第一个输入的unique&#xff0c;那么需要记录下读入的顺序&#xff0c;可以开辟一个数组inputs[…

SWT图像处理入门

SWT图像处理入门 Standard Widget Toolkit ( SWT &#xff0c;标准窗口小部件工具箱)&#xff0c;是在 Eclipse 平台上使用的窗口小部件工具箱&#xff0c;它能向开发者提供和本机平台一致的用户界面和比较稳定的性能&#xff0c;也提供了强大的图像处理功能。本文首先介绍 SWT…

MyEclipse中的快捷键

MyEclipse 快捷键1(CTRL)-------------------------------------Ctrl1 快速修复CtrlD: 删除当前行 CtrlQ 定位到最后编辑的地方 CtrlL 定位在某行 CtrlO 快速显示 OutLine CtrlT 快速显示当前类的继承结构 CtrlW 关闭当前Editer CtrlK 快速定位到下一个 CtrlE 快速显示当…

CocoaPods原理(一)

CocoaPods介绍 CocoaPods 是开发 OS X 和 iOS 应用程序的一个第三方库的依赖管理工具。利用 CocoaPods&#xff0c;可以定义自己的依赖关系 (称作 pods)&#xff0c;并且随着时间的变化&#xff0c;以及在整个开发环境中对第三方库的版本管理非常方便。 CocoaPods 背后的理念主…

1055 The World‘s Richest

开始的做法是&#xff0c;对于每一个case&#xff0c;都在整个person数组内进行遍历&#xff0c;把所有年龄符合要求的都放进一个临时数组&#xff0c;然后对临时数组进行排序&#xff0c;再根据要求的数目输出。但是这么做会有一个测试用例因为超时而通不过。 穷则思变。于是…

IOS时间传递机制简记

事件传递顺序&#xff1a;自定义View -- > UIview --> RootViewController --> UIWindow -->UIApplication -->Appdelegate -->nil 注&#xff1a; //分发事件&#xff0c;将当前的触摸事件分发给当前对象的下一个响应者 //如果当前对象处理了当前事件&am…

HDOJ2270(How Many Friends Will Be Together With You)

#include <iostream>using namespacestd;const int MAX 1000005;intfr[MAX];intmain(){ int n, i, tt, sum; while(cin>>n) { for(i 1; i < n; i) fr[i] i;//初始化&#xff0c;一开始每个都是独立的&#xff0c;并无朋友 …