您当前的位置: 首页 > 

Peter_Gao_

暂无认证

  • 0浏览

    0关注

    621博文

    0收益

  • 0浏览

    0点赞

    0打赏

    0留言

私信
关注
热门博文

自顶向下与自底向上编程思想的对比

Peter_Gao_ 发布时间:2021-07-29 15:39:37 ,浏览量:0

在国内的网站上搜索什么叫“自底向上”编程,给人的感受似乎是同一个问题有两种解决思路,一个是“自顶向下”,一个是“自底向上”。但你仔细看那些文章的讲解,其实说的都只是“自顶向下”。

为了说清楚“自底向上”编程,首先赘述一下什么叫做“自顶向下”编程。

  自顶向下编程 自顶向下编程一般会好理解一点。首先从整体分析一个比较复杂的大问题。为了解决这一问题,必须把它拆分来看,应当解决哪几个小问题,然后再逐步细分到更小的问题,直到每个问题对我们来说,都已经很简单。解决了所有的小问题,逐步向上汇总,就完成了最初的复杂问题。值得强调的是:从小问题汇总到最后的复杂问题,这是“自顶向下”编程的一个过程,这不叫“自底向上”编程。

  它的本质是什么 “自顶向下”编程是典型的工程师思维方式,一事一议地解决问题。大问题分解为小问题的具体方法,视实际操作者水平高低,会有很大的差异。但即使是一个新手,也有办法入手。这种解决问题的方式,效率是比较高的,但可重复性很低。下次遇到一个即使是类似的问题,我们会发现,分析方法或许是可以重用的,但具体的代码和工作量往往难以重用。

  自底向上编程 自底向上编程,是这样一种操作过程:先描述,后编程。当我们面对一个复杂的大问题的时候,我们首先把它泛化为一大类问题,用一些基本概念对所有这些问题进行描述。然后逐步增加那些必不可少的概念,直到我们能够完整而细致地把这些问题描绘清楚。这一过程有点像构建一个公理体系。我们逐渐增加公理的数量,直到整个体系中的所有感兴趣的命题都可以用这些公理推导出来。

又像构建一种语言(DSL),这种语言比我们所使用的编程语言的粒度大很大,提供了描述问题时所用的大块抽象积木。同时它比我们描述问题所用的自然语言更加清晰准确,因为它是可以由计算机理解的语言。

在这样的描述工作完成之后,我们开始编程。首先实现的是这些公理体系,或者说是这些DSL的基本概念。这是整个复杂问题的底部。在此之上,我们继续添加定义和定理,或者说添加DSL中的高阶概念。这些逐步构建起来的更加复杂的模块,让我们距离最初的复杂问题越来越近。直到最初的问题被证明,或者说被DSL中的高阶概念表达,也即被解决。这就是“自底向上”的编程过程。

它的本质又是什么 自底向上”的编程过程,远比“自顶向下”编程复杂得多。它的目标不是解决一个具体的问题,而是解决一类具有普遍性问题。它的着眼点不仅仅是眼前问题的解决,而是程序在需求改变下的健壮性。

两种编程方式举例 我们从一个具体的例子,来看两者的不同。

比如现在我们的需求是:求一个数字列表的每个数的平方和。

自顶向下的编程思路是这样:

首先设一个累加器并预设初始值为0 然后遍历整个列表, 取出列表中的每个数字, 计算平方, 并且累加。 思路很简单,具体代码如下:

  a=[1,2, 3, 4,5]   def calc(lst):     sum= 0     for i in lst:         sum+= i**2     return sum   squareSum= calc(a) print(squareSum) 它的特点是思路直接,效率高。这是一个紧密耦合的高度定制化的功能,除了解决这个问题之外,不会再有什么其他的用处。如果需求发生了某种变化,只能重建一个新的函数来实现。虽然代码的基本思路是可以重用的,但给人以某种一事一议的特殊感。

自底向上的编程思路是这样:

首先这个问题的本质是:对一个列表中的每个数字做某种处理后再进行某种形式的合并。 第一个某种处理:是在进行平方处理,我们应当有一个平方的概念(函数)。 第二个某种形式的合并,是在累加,我们应当有一个累加的概念(函数)。 再然我们实现一个先处理后合并的机制。 将这三者组合起来,解决问题。 代码如下:

from functools import reduce   a=[1,2, 3, 4,5]   def sum(a, b):     return a+b def sqare(a):     return a**2 def reduceMap(mapFunc, redFunc, lst):     return reduce(redFunc, map(mapFunc, lst))   squareSum= reduceMap(sqare, sum, a) print(squareSum) 它的特点是思考方式不那么直接,开发效率和运行效率可能都会略低一些。但这种解决问题的方法似乎在某种角度来看“更接近问题的本质”,它是试图解决一大类问题,这类问题的需求由三个独立的函数来描述,如果三处的具体需求发生改变,我们只须修改一个函数即可。

如果需求从此不变,当然第一种方法是简单的。但需求是必然变化的。

如果需求发生了改变 比如,我们改一下需求:在有些情况下只对列表中的奇数求平方和。

自顶向下的编程思路就不展开了,增加一个函数即可。复制粘贴后略做修改:

  a=[1,2, 3, 4,5]   def calc(lst):     sum= 0     for i in lst:         sum+= i**2     return sum   def calc2(lst):     sum= 0     for i in lst:         if i%2==1:             sum+= i**2     return sum   # squareSum= calc(a) squareSum= calc2(a) print(squareSum) 这两个函数看起来就多少感觉有些别扭了,不但重复了相似的逻辑结构,而且都相当特殊,几乎不会有复用的机会。可以预见到如果继续增加需求,还会继续增加函数。

自底向上的编程思路是这样:

新的需求增加了判断奇偶数的概念,增加一个函数。 新的需求增加了从列表种进行挑选的概念,增加一个函数。 同时新的函数可以覆盖原来的函数,旧的函数可以做修改(可选优化) 代码如下:

from functools import reduce   a=[1,2, 3, 4,5]   def sum(a, b):     return a+b def sqare(a):     return a**2 def isOdd(a):     return a%2==1 def reduceMapFilter(mapFunc, redFunc, fltFunc, lst):     return reduce(redFunc, map(mapFunc, filter(fltFunc, lst))) def reduceMap(mapFunc, redFunc, lst):     # return reduce(redFunc, map(mapFunc, lst))     return reduceMapFilter(mapFunc, redFunc, lambda x:x, lst)   # squareSum= reduceMap(sqare, sum, a) squareSum= reduceMapFilter(sqare, sum, isOdd, a) print(squareSum) 虽然这个思路对于一个需求的改动,增加了两个函数,但函数的功能非常基础,且逻辑结构不重复。随着需求的继续增加,可以预见,这些函数会有更多复用的机会(实际上,考虑到旧函数的修改,新函数已经开始复用了)。如果我们能够预见到整个软件的需求会向这个方向发展,我们会考虑按这个思路来实现代码。

总结一下 自顶向下的编程思路适合规模较小、需求高度稳定、短期项目。思路的重点的问题分解。简单直接好理解,上手速度快,代码运行效率高。如果你给别人做外包开发,相信这种编程思路是最佳选择。

自底向上的编程思路是否规模较大、需求变化较多、长期项目。思路的重点是设计描述语言。思维过程复杂,运行效率略低。初期上手速度慢,后期随着复用程度的提高,开发会有加速效应。如果你做一个自己的研究项目,应当尝试这种编程思路。

原文链接:https://blog.csdn.net/xiaorang/article/details/105464122

自顶向下不是万能的

需求发生变化时。会非常尴尬

变化是需求的本质特征

内部或外界的环境一旦发生小小的变化。就会造成非常大的变动

个人---全然掌控-----》简单的软件逻辑《-----全然计划的模式

小组协作---掌控变化----》庞大的软件规模---产生--》自适应变化《-----解决-----主流解决方式:面向对象

面向对象正是採用自底向上的设计风格

打印控制台表格2

实际开发中,使用混合风格,依据项目的要求而定

需求:不变。变

不变---》多种风格选择---》完毕任务

变化---》估算变化---》确定风格---》完毕任务

Excel是把每个小格子确定为一个对象,细致的去设计这个对象应当拥有的功能和其它对象的关系

自底向上的分析:

想象每个小格子画出来以后进行组合就能完毕要求。

构造这种一个小对象,把它的功能调试完备,通过组合完毕需求

https://www.cnblogs.com/gcczhongduan/p/5337397.html

关注
打赏
1664521772
查看更多评论
立即登录/注册

微信扫码登录

0.0358s