05设计实践

设计实践

1.迭代

? 打你你在备选的设计方案之中循环并且尝试一些不同的做法时,你将同时从高层和低层的不同视角去审视问题。你从高层视角中得到的大范围途径会有助于你把相关的低层细节纳入考虑。你从低层视角中所获得的细节也会为你的高层决策奠定基础。这种高低层面之间的互动被认为是一种良性的原动力,它所创建的结构要远远稳定与单纯自上而下或自下而上创建的结构。

? 当你首次尝试得出了一个看上去足够好的设计方案后,请不要停下来!第二个尝试几乎肯定会好于第一个,而你也会从每次的尝试中都有所收获,这有助于改善整体设计。

2.分而治之

? 没有人的头脑能够装得下一个复杂程序的全部细节,这对设计也同样有效。把程序分解为不同的关注区域,然后分别处理每一个区域。如果你在某个区域里碰到了死胡同,那么就跌代。

? 增量式地改进是一种管理复杂度的强大工具。正如 Polya 在数学问题求解中所建议的那样——理解问题、形成计划、执行计划,然后再回顾你的做法。

3. 自上而下和自下而上的设计方法

? 自上而下的设计从某个很高的抽象层次开始。你定义出基类或者其他不怎么特殊的设计元素。在开发这一设计的过程中,你逐渐增加细节的层次,找出派生类、合作类以及其他更细节的设计元素。自下而上的设计始于细节,向一般延伸。这种设计通常是从寻找具体对象开始,最后从细节之中生成对象以及基类。

  • 自上而下的论据

    ? 居于自上而下方法背后的知道原则是这样一种观点:人的大脑在同一时间只能集中关注一定量的细节。如果你从一般的类出发,一步步地把他们分解成为更具体的类,你的大脑就不会被迫同时处理过多的细节

    ? 这种分而治之的过程在某些意义上来说也是迭代的。首先,说它是迭代的,因为你通常不会再完成一层分解之后停下来。你还会继续分解几层。其次,说它是迭代的,是因为你通常不会满足于你的第一次尝试。你用一种方法来分解程序。在分解过程中的不同阶段,你需要就采用什么方法去分解子系统做出选择,给出继承关系树,形成对象的组合。你做出选择,然后看看是什么结果。接下来,你又换用另一种方法重新开始分解,以便看清方法是否效果更佳。这种尝试几次之后,你就会很清楚哪些方法会奏效,以及他们能够奏效的原因。

    ? 如何确定分解的程度呢?持续分解,直到看起来在下一层直接编码要比分解更容易。一直做到设计思路已显而易见而且非常容易,以致 你对继续分解下去已近产生了厌倦。那时候你就完成了分解工作。如果设计思路还不明了,那么请再多做些。如果目前的解决方案对你来说都有些棘手,那么日后他人再去面对的时候也肯定会感到负担重重。

  • 自下而上的论据

    ? 有时候自上而下的方法会显得过于抽象,很难入手去做。如果你倾向于用一种更实在的方法, 那么可以尝试自下而上的方法。问你自己,“我对这个系统该做的事情知道些什么?”毫无疑问,你可以回答这个问题。你可能会找出一些能够分配给具体类的底层的职责。例如,你知道一个系统需要对报表进行格式化,为报表计算数据,把标题居中,在屏幕上显示报表,以及打印该报表等等。一旦你找出了一些底层的职责,你通常会感到,再从顶层去观察系统已经舒服些了。

    ? 在另一些情况中,设计问题里的一些主要属性是由底层决定的。你可能需要去与硬件设备打交道,他们的接口需求决定了你的设计里很大一部分。

    ? 下面是在做自下而上合成的时候你需要考虑的一些因素:

    (1)问你自己,对系统需要做的事项,你知道些什么。

    (2)根据上面的问题,找出具体的对象和职责。

    (3)找出通用的对象,把它们按照适当方式组织起来——子系统、包、对象组合,或者集成——看哪种方式适合。

    (4)在更上面一层继续工作,或者回到最上层尝试向下设计。

  • 其实并没有争议

    ? 自上而下的策略和自下而上的策略的最关键区别在于,前面是一种分解策略而后者是一种合成策略。前者从一般性的问题出发,把该问题分解成可控的部分。后者从可控的部分出发,去构造一个通用的方案。这两种方法都有各自的强项和弱项,如果你想在设计中采用它们的时候,就需要予以考虑。

    ? 自上而下设计的强项是它很简单,因为人们很善于把一些大的事情分解成为小的组件,而程序员则更精于此道。

    ? 自上而下设计的另一个强项是你可以推迟构建的细节。软件系统常常会受到构建细节变化(例如文件结果或者报表格式发生的变化)的骚扰,因此,尽早知道应该把这些细节隐藏在 继承体系的底层类中,是非常有益的。

    ? 自下而上设计的一个强项是通常能够较早找出所需的功能,从而带来紧凑的、结构合理的设计。如果类似的系统已经做过,那么自下而上的设计让你能审视已有的系统,并 提出“我能重用些什么?”一类的问题,由此出发开始新系统的设计。

    ? 自下而上设计的一个弱项是很难完成独立的使用它。大多数人都很善于把大概念分解为小概念,而不擅长从小概念中得出大概念。这就像在自己组装玩具:我想自己已经组装完成了,可为什么盒子里还有零件呢?所幸的是,完全不必仅适用自下而上这一种设计方法。

    ? 自下而上设计的另一弱项是,有时候你发现自己无法适用手头已有的零件来构造整个系统。你不可能用砖块来建造飞机。你可能要先做高层设计,才能知道底层需要什么零件。

    ? 总而言之,自上而下设计通常比较容易上手,但是有时候会受底层复杂度的影响,这种影响甚至有时候会使事情变得比实际的情况更复杂。自下而上设计开始起来比较复杂,但是在早期鉴别出系统的复杂度,却有助于设计出更好的高层类。当然这样做的前提是复杂度没有把整个系统破坏掉。

    ? 最后要说的是,自上而下和自下而上设计并不是互相排斥的——你会收益于二者的相互协作。设计时一个启发式(试探)的过程,这意味侄儿没有任何解决方案能够保证万无一失。设计过程充满了反复的试验,请多尝试些设计方法,知道找到最佳的一种。

4. 建立试验性原则

? 有些时候,除非你更好地了解了一些实现细节,否则很难判断一种设计方法是否奏效。比如说,在知道它能满足性能需求之前,你很难判断某种数据库的组织结构是否适用。在选定系统使用的图形界面(GUI)程序之前,你也很可能判断不出某一特定子系统的设计是否到位。这些都是软件设计中本质性“险恶”的例子——除非你部分的解决了某一设计问题,否则你无法完整地定义出该设计问题。

? 有一种技术能够低成本地解决这个问题,那就是建立试验性原型。“建立原型”一词对不同人来说具有不同的含义。在这里,建立原型指的是“写出用于回答特定设计问题的、量最少且能够随时扔掉的代码”。

? 如果开发人员没有把握住用最少代码回答图问题的原则,那么原型方法的功效可能就会大打折扣。假如说,设计问题是“我们选定的数据库框架能否支撑所需的交易量?”你不需要为了这一问题而编写任何产品代码,你也不需要去了解数据库的详情。你只需要了解能估计出问题范围的最少信息——有多少张表、表中有多少条记录,等等。接下来你就可以用Table1、Table2、Column1、Column2等名字写出最简单的原型代码,往表里随意填入些数据,然后做你所需要的性能测试。

? 当有关设计的问题不够特殊的时候,原型同样也会失效。诸如“这样的数据库框架能否工作?”的设计问题并没有为建议原型提供多少指导。而像“这个数据库框架能不能在X、Y和Z的前提下支持每秒1000次交易?”这样的问题则能为建立原型提供更坚实的基础。

? 最后一个可能会给原型带来风险的做法是,开发人员不把原型代码当做可抛弃的代码。我发现,如果开发人员相信某段代码将被 用在最终产品里,那么他根本不可能写出最少数量的代码来。这样做做种其实是在实现整个系统,而不是在开发原型。相反,如果你建立了这样的概念,那就是一旦回答了所提出的问题,这段代码就可以被扔掉,那么你就可以把上述风险减到最小。避免产生这一问题的一种做法就是用于产品代码不同的技术来开发原型。你可以用Python来为Java设计做原型,或者用 Office PPT 来模拟用户界面。如果你必须要用同一种技术来开发原型,那么可采纳一个非常实用的标准:在原型中的类或者包的名称之前加上 prototype 前缀。这样至少能保证程序员在试图拓展原型代码之前能够三思。

? 一旦依照上述原则加以应用,那么原型就会成为设计者手中用来出库险恶设计问题的有力工具。如果不遵照上述原则,那么原型就会给设计再平添许多风险。

5. 合作设计

? 在设计过程中,三个臭皮匠顶得上一个诸葛亮,而不论组织形成的正式与否。合作可以以下面的任意一种方式展开。

  • 你随便走到一名同事的办公桌前,向他征求一些想法。
  • 你和同事坐在会议室里,在白板上画出可选的设计方案。
  • 你和同事坐在键盘前面,用你们的编程语言做出详细的设计,换句话说,你们可以采用结对编程。
  • 你约一名或者多名同事来开会,和他们过一遍你的设计想法。
  • 你身边没有能检查你的工作,因此当你做完一些初始工作后,把他们全放进抽屉,一星期后再回来回顾。这时候你会把该忘的都忘掉,正好可以给自己做一个不错的检查。
  • 你向公司以外的人求助:在某个特定的论坛或者新闻组里提出。
6. 要做多少设计才够

? 有些时候,编码之前只制定出系统架构的一个最小梗概.而在另一些时候,开发团队会把设计做的非常详细,是编码变成了一种近乎机械的工作。

? 如果设计层次的问题是留给程序员个人去解决的话,那么,当设计下降到你曾经完成过的某项任务的层次,或者变成了对这样一想任务的简单修改或者扩充的时候,你很可能就会停止设计而马上开始编码。

? 如果在编码之前我还判断不了应该再做多深的设计,那么我宁愿去做更详细的设计。最大的设计失误来自于我误认为自己已经做得很充分,可时候却发现还是做得不够,没能发现其他一些设计挑战。换句话说,最大的设计问题通常不是来自于那些我认为是很困难的,并且在其中做出了不好的设计的区域;而是来自于那些我认为很简单的,而没有做出任何设计的区域。我几乎没有遇到过因为做了太多设计而受损伤的项目。

? 另一方面,我偶尔会看到一些项目因太过于专注对设计进行文档化而导致失败。Gresham 法则是这样说的,“程序化的活动容易把非程序化的活动驱逐出去”。过早的去润色设计方案就是这一法则所描述的例子。我宁愿看到有80%的设计精力用于创建和探索大量的备选设计方案,而20%的精力用于创建并不很精美的文档,也不愿看到把20%的精力花在创建平庸的设计方案上,而把80%的精力用于对不两个设计进行抛光润色

7. 记录你的设计成果

? 传统的记录设计成果的方法是把它写成正式的设计文档。然而,你还可以用很多种方法来记录这一成果,而这些方法对于那些小型的、非正式的项目或者只需要轻量级的记录设计成果的方式的项目而言效果都很不错。

  • 把设计文档插入到代码里

    在代码注释中写明关键的设计决策,这种注释通常放在文件或者类的开始位置。如果你同事使用类似于 JavaDoc 这样的问题提取工具,那么这种方法会确保设计文档对于开发这部分代码的程序员来说是立等可取的,同时也有助于程序员保持代码和设计文档之间的相当不错的同步。

  • 用 Wiki 来记录设计讨论和决策

    把我们的设计讨论写到项目的WIki里去。尽管文字录入要比较麻烦一些,但这样会自动地记录下你们的设计讨论和设计决策。如果使用Wiki,你可以用图片来弥补文字讨论的不足,并连接支持该设计决策的网站、白皮书及其他资料。如果你的开发团队在地理位置上是分布式的,那么这种技术会非常有帮助。

  • 写总结邮件

    每次就设计展开谈论后,请采取这种做法,即指派某人来写出刚才讨论的纲要——特别是那些决定下来的事项——然后发送给整个项目组。在项目组的公共电子邮件文件夹里保留一份备份。

  • 使用数码相机

    把白板上画出的图表照成相片然后嵌入到传统的文档里,这样做可以带来事半功倍的效果,因为它的工作量只是用画图工具画设计图表的1%,而受益却能达到保存设计图表的80%。

  • 保留设计挂图
  • 使用 CRC (类、职责、合作者)卡片
  • 在适当的细节层创建 UML图

    一种流行的绘制设计图的方法是由对象管理组织定义的统一建模语言(UML)。UML 提供了一套丰富的、形式化的表示法,可用于设计实体及其关系。你可以用非正式的 UML 图来帮助讨论和发现设计细节。由于 UML 是标准化的,因此在交流设计观念时大家都能理解它,同时还能加快团队共同讨论各种设计方案的速度。

8. 对流行的设计方法的评价

? 你怎样擦能判断出需要多少设计才够呢?这是一个主观判断,没有人能完美地回答它。不过,在你没有足够的信心去判断最佳设计量的时候,请记住有两种情况一定是不对的:设计所有细节和不做任何设计。这两个由位于立场两端的极端主义者所倡导的做法,恰恰被证明是仅有的两个永远是错误的做法。

? 正如 P.J. Plauger所言,“你在应用某种设计方法时越教条化,你所能解决的现实问题就会越少”。请把设计看成是一个险恶的、杂乱的和启发式的过程。不要停留于你所想到的第一套解决方案,而是去寻求合作,探索简洁性,在需要的时候做出原型,迭代,并进一步迭代。你将对自己的设计成果感到满意。

原文地址:https://www.cnblogs.com/rock-cc/p/9839352.html

时间: 2024-10-18 13:02:56

05设计实践的相关文章

《响应式Web设计实践》学习笔记

原书: 响应式Web设计实践 第2章 流动布局 1. 布局选项 传统的固定布局中存在很多问题, 随着屏幕大小的越来越多元化, 固定布局已经不能适用了. 在流动布局中, 度量的单位不再是像素, 而是变成了百分比. 弹性布局与流动布局类似, 但是通常情况下, 弹性布局中会以em来作为单位. 带来一个好处是随着用户增大或减小字体, 适用弹性布局的元素的宽度也会等比例地变化. 但是其也可能出现水平滚动条 混合布局 媒体查询: 媒体查询允许根据设备的信息----诸如屏幕宽度, 方向或者分辨率等属性来使用不

JavaScript网站设计实践(七)编写最后一个页面 改进表单

原文:JavaScript网站设计实践(七)编写最后一个页面 改进表单 一.最后一个页面 contact.html.改进表单 在该页面实现的功能: 几乎所有的网站都会有表单填写,对于用户输入和填写的数据,首先我们一般现在前台验证,然后再去后台验证. 在前台最简单的验证:检查必填字段是否填写.填写格式是否符合要求等. 每个表单里面,当获取到输入焦点时,令提示文本消失 现在开始动手来写. 1.实现思路 (1)在这个表单里会验证的是必填字段和邮箱格式是否正确.首先,把判断必填字段和邮箱格式分别写在两个

JavaScript网站设计实践(一)网站结构以及页面效果设计

原文:JavaScript网站设计实践(一)网站结构以及页面效果设计 这是JavaScript DOM编程艺术里的构建JavaScript网站设计的例子,这本书给我学习JavaScript带来许多启发,在这个乐队宣传网站中,把前面学到的知识点整合在这个项目了.在这里记录下实现这个乐队的宣传网站的具体过程,加深理解.好,从现在开始来实现这个JavaScript网站实战. 一.网页的结构 由三个部分组成:头部.导航.内容 效果图是这样的(勉强看,有点不美观.哈哈): 二.网站的的结构 这是我的项目目

JavaScript网站设计实践(二)实现导航栏当前所选页面的菜单项高亮显示

一.(一)中的代码还可以修改的地方. 在(一)中,如果是运行在服务器下,如apache等,可以把head和navigation的div抽取出来,放置在另一个html文件里,然后在页面中,include进来.这样,当要对导航栏进行修改时,只需要修改一个文件,而不用修改所有相关的页面文件.不过,我这里没有这样做,没有抽取出来. 二.实现当前页面的标识+不同页面的head头部背景图片的改变 现在在(一)实现的基础之上,来实现导航栏当前所选页面的菜单项高亮显示,让访问者一路了然知道"我正在这里"

EntityFramework之领域驱动设计实践

EntityFramework之领域驱动设计实践 - 前言 EntityFramework之领域驱动设计实践 (一):从DataTable到EntityObject EntityFramework之领域驱动设计实践 (二):分层架构 EntityFramework之领域驱动设计实践 (三):案例:一个简易的销售系统 EntityFramework之领域驱动设计实践 (四):存储过程 - 领域驱动的反模式 EntityFramework之领域驱动设计实践 (五):聚合 EntityFramewor

JavaScript网站设计实践(四)编写about.html页面,利用JavaScript和DOM,选择性的显示和隐藏DIV元素

一.现在我们在网站设计(三)的基础上,来编写about.html页面. 这个页面要用到的知识点是利用JavaScript和DOM实现选择性地显示和隐藏某些DIV about.html页面在前面我们为了看导航栏菜单项高亮显示时,已经写了部分内容,只是那时写的代码没有实现div显示和隐藏,现在就在之前编写的基础上,为页面添加显示和隐藏div的效果. 没有写JavaScript之前看到的效果: 实现后的效果图: 这个就是我们现在要做的效果. 1.背景: 我们在about.html页面中写了一个ul列表

JavaScript网站设计实践(六)编写live.html页面 改进表格显示

原文:JavaScript网站设计实践(六)编写live.html页面 改进表格显示 一.编写live.html页面,1.JavaScript实现表格的隔行换色,并且当鼠标移过时当前行高亮显示:2.是输出表格中的abbr标签的内容 实现后的效果图是这样的: 1.实现思路 在输出表格的时候,给出一个判断,如果偶数或是奇数行我们想换色,则添加一个class为odd的值,在这个class里就设置了表格不同颜色tr行. 这里用到了一个判断函数:(下面是两个不同的方法,任选其一) 法一://隔行换色 添加

JavaScript网站设计实践(三)设计有特色的主页,给主页链接添加JavaScript动画脚本

原文:JavaScript网站设计实践(三)设计有特色的主页,给主页链接添加JavaScript动画脚本 一.主页一般都会比较有特色,现在在网站设计(二)实现的基础上,来给主页添加一点动画效果. 1.这里实现的动画效果是:当鼠标悬停在其中某个超链接时,会显示出属于该页面的背景缩略图,让用户知道这个链接的页面大概内容是什么. 效果图: 2.实现这个效果的思路 (1)把主页的几个链接的背景图片缩放到150px*150px,拼成一张750*150的图片,并保存为slideshow.png,存放到ima

JavaScript网站设计实践(五)编写photos.html页面,实现点击缩略图显示大图的效果

原文:JavaScript网站设计实践(五)编写photos.html页面,实现点击缩略图显示大图的效果 一.photos.html页面,点击每一张缩略图,就在占位符的位置那里,显示对应的大图. 看到的页面效果是这样的: 1.实现思路 这个功能在之前的JavaScript美术馆那里已经实现了. 首先在页面中使用ul列表显示出所有的缩略图,然后使用JavaScript,for循环检查出当前点击的是哪一张图片,最后把这张图片给显示出来. 用到三个函数:显示图片函数.创建占位符预装图片.点击显示图片