Jiahonzheng's Blog

自顶而下-逐步求精

字数统计: 1.9k阅读时长: 6 min
2017/12/31 Share

在学习和生活中,我们难免会碰到这样的情景:“这件事,我该怎么做?”。如果对生活有了较为仔细的观察,我们会发现有人从事这样的职业——咨询顾问,而他们的职能就是帮助人去解决问题。那么问题来了,作为一个“行外人”,咨询顾问怎么知道某件具体的事情该怎么解决呢。

这是一个很好的问题,涉及到一种重要的哲学思想——“自顶而下”。当然,咨询顾问还有一些更为高效的思维框架解决客户的问题,这里不展开讨论。

在本篇博文中,笔者给大家介绍一种与上述思想异曲同工的软件设计思想——“自顶而下,逐步求精”。

结构化程序设计方法

1965 年,E.W.Dijikstra 提出了结构化程序设计的方法,是软件发展的一个重要的里程碑,它的主要观点是采用自顶而下、逐步求精以及模块化的程序设计方法。

结构化程序设计方法告诉我们,任何程序都可以由顺序、选择、循环三种基本结构组成,更强调程序的易读性。

网络不给力

自顶而下

程序设计时,应先考虑总体,后考虑细节;先考虑全局目标,后考虑局部目标。不要一开始就过多追求众多的细节,先从最上层总目标开始设计,逐步使问题具体化。

逐步求精

对复杂问题,应设计一些子目标作为过渡,逐步细化。

模块化

模块化是把程序要解决的总目标分解为子目标,再进一步分解为具体的小目标,把每一个小目标称为一个模块。

智能洗衣机的例子

在本节中,我们使用“自顶而下,逐步求精”的程序设计方法,设计智能洗衣机工作程序。

洗衣程序,是我们要解决的大问题,那什么是洗衣程序呢。经过脑力风暴,我们知道洗衣机完成正常洗衣功能需要经过注水、浸泡、洗涤、漂洗、脱水五个过程:

  • 注水:用户选择所需用水量,加入洗涤液,并注入对应水量
  • 浸泡:静置一定时间,使得洗涤液能充分与衣物脏物质反应
  • 洗涤:旋转底部转盘、摇动直筒,使衣物与筒壁摩擦,实现洗涤目的
  • 漂洗:待将筒中的洗涤废液排出后,再次注水至淹没衣物,静置一定时间,再通过底部转盘的旋转和直筒的摇动,除去衣物中残余的洗涤液,再次排水
  • 脱水:滚筒高速旋转,通过离心作用对衣物进行脱水操作

分解为 4 个小问题,我们已经完成了“自顶而下”的步骤,接下来我们需要对上述四个小问题进行细化工作,从而得到。

  • 如何确定停止注水的时间?
    • 通过水位传感器反馈实时水位指标,作为停止注水的触发因素。
  • 如何确定洗涤过程中,旋转转盘和摇动滚筒的运行时间和运行方式?
    • 待工程师测试最佳洗涤工作模式。
  • 如何检测是否除尽衣物中的洗涤成分?
    • 通过对桶内废液进行 pH 值检测,若达到一定阈值(即漂洗干净),则可进入下一阶段,否则重新进行漂洗阶段。
  • 如何确定停止脱水的时间?
    • 通过对排出液的流量检测,若某时刻排出液流量低于某一阈值,该时刻即为停止脱水的时刻。
  • 运行时的警报提示?
    • 当用户已选择所需用水量,但没有检测到注入水的流量变化,即没有水注入滚筒,则发起警报。
    • 在漂洗和脱水过程中,如果排出液流量没有变化(仍为零),即废液无法排出,则发起警报。
    • 当用户在工作阶段打开洗衣机盖,则发起警报。
  • 正常洗衣和快速洗衣模式的区别?
    • 快速洗衣模式,缺少了浸泡模式,并且漂洗模式和脱水模式整合。

在不断地细化子问题后,我们可通过下列伪代码实现智能洗衣机的功能。

1
2
3
4
5
6
7
8
9
10
11
12
13
14
15
16
17
18
19
20
21
22
23
24
25
26
27
28
29
30
31
32
33
34
35
36
37
38
39
40
41
42
43
44
45
46
47
48
49
50
51
52
53
54
55
56
57
58
59
60
61
62
63
64
65
66
67
68
begin
waterinswitch(false)
wateroutswitch(false)
motorrun(stop)

input 水量
waterinswitch(true)
while (getwatervolume() <= 水量)
if (getwatervolume()恒为零)
halt(failure)
end if
end while
waterinswitch(false)

while (timecouter() <= 浸泡预设时间)
end while

while (timecounter() <= 洗涤预设时间)
motorrun(left, 左转预设次数)
motorrun(right, 右转预设次数)
摇动滚筒(预设强度)
end while
motorrun(stop)

wateroutswitch(true)
while (getwatervolume() != 0)
end while
wateroutswitch(false)

waterinswitch(true)
while (getwatervolume() != 水量)
if (排出水量没有变化)
halt(failure)
end if
end while
waterinswitch(false)

while (timecouter() <= 静置预设时间)
静置()
end while

while (pH()不在漂洗成功预设pH值范围)
motorrun(left, 左转预设次数)
motorrun(right, 右转预设次数)
摇动滚筒(预设强度)
end while

wateroutswitch(true)
while (getwatervolume() != 0
if (排出水量没有变化)
halt(failure)
end if
end while

while (排出水量不是极其小)
motorrun(left)
if (排出水量没有变化)
halt(failure)
end if
end while
motorrun(stop)

halt(success)

waterinswitch(true)
wateroutswitch(true)
motorrun(stop)
end

优点与缺点

在这一小节中,我们对结构化程序设计方法进行大概的优缺点分析。

优点

结构化程序设计方法,先采用了“自顶而下,逐步求精”的方法,将问题逐步分解为小问题,并且不断细化小问题,最后通过模块化的方法,实现每个小问题的解决,从而解决大问题。

  • 整体思路清楚,目标明确。
  • 设计工作中阶段性非常强,有利于系统开发的总体管理和控制。
  • 在系统分析时可以诊断出原系统中存在的问题和结构上的缺陷。

缺点

结构化程序设计方法,在拥有众多优点的同时,也存在一些不可避免的缺点。

  • 用户要求难以在系统分析阶段准确定义,致使系统在交付使用时产生许多问题。
  • 用系统开发每个阶段的成果来进行控制,不能适应事物变化的要求。
  • 系统的开发周期长。

题外话

掌握“自顶而下”的思想,对个人是很有必要的,熟练地运用这种思想,能让我们拥有一套结构化思维体系

MBA 智库对结构化思维的定义:

一个人在进行问题解决时能站在整体的角度,遵循启发性的原则,充分发挥左右脑的功能,通过对问题的自我理解和分析,充分利用已有的认知结构透彻地认识问题,合理的分解问题,循序渐进,逐步求精,从而进一步完善自己的认知结构,全面完整地对问题进行系统思考和解决。

如果我们能够经过有意识的长期训练,培养出这样的思维方式和思维习惯,那么在大部分问题上,我们能做到像咨询顾问一样,对问题有个全面深刻的理解,对问题的解决方案也更为到位。

最后,给大家安利一本关于结构化思维的书——《金字塔原理》

网络不给力

作为程序员,我们不仅要会编程,还要会生活

CATALOG
  1. 1. 结构化程序设计方法
    1. 1.1. 自顶而下
    2. 1.2. 逐步求精
    3. 1.3. 模块化
  2. 2. 智能洗衣机的例子
  3. 3. 优点与缺点
    1. 3.1. 优点
    2. 3.2. 缺点
  4. 4. 题外话