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

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

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

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

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

又像构建一种语言(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

自顶向下与自底向上编程思想的对比相关推荐

  1. Java核心技术(卷1) 10th 总结(兼与Java编程思想等对比)

    总结   前一段时间把<核心卷>的卷一看完了,后来又看完了<图解TCP/IP>,月初考了一个证券从业证书,还有实验室的事情,实在是很忙.眼瞅着到月底了,还是抽出时间做个总结.关 ...

  2. 各种设计模式对比及编程思想总结

    各种设计模式对比及编程思想总结: 设计模式 一句话归纳 工厂模式(Factory) 只对结果负责,不要三无产品 单例模式(Singleton) 保证独一无二 适配器模式(Adapter) 需要一个转换 ...

  3. 第1章 JVM语言家族概览 《Kotin 编程思想·实战》

    第1章 JVM语言家族概览 天地和而万物生,阴阳接而变化起.<荀子·礼记> 1.1 编程语言简述 1.1.1 编程语言是什么 所谓编程语言只是一个抽象的规范,而编译器是这个规范的实现,它是 ...

  4. 编程思想:面向对象和面向过程

    何谓面向对象?何谓面向过程?对于这编程界的两大思想,一直贯穿在我们学习和工作当中.我们知道面向过程和面向对象,但要让我们讲出来个所以然,又感觉是不知从何说起,最后可能也只会说出一句就是那样啦,你知道啦 ...

  5. 在java中三种编程思想(OOA,OOD,OOP)

    在java中三种编程思想:OOA,OOD,OOP OOA 一.OOA的主要原则. 二.面向对象分析产生三种分析模型 三.OOA的主要优点 四.OOA方法的基本步骤 OOD 一.OOD背景知识 二.OO ...

  6. python实现自顶向下,自底向上

    常用的算法设计思想主要有动态规划.贪婪法.随机化算法.回溯法等等,这些思想有重叠的部分,当面对一个问题的时候,从这几个思路入手往往都能得到一个还不错的答案. 本来想把动态规划单独拿出来写三篇文章呢,后 ...

  7. python 静态方法_Python编程思想(25):方法深度解析

    -----------支持作者请转发本文-----------李宁老师已经在「极客起源」 微信公众号推出<Python编程思想>电子书,囊括了Python的核心技术,以及Python的主要 ...

  8. Java编程思想(第4版)(评注版)

    传世经典书丛  Java编程思想(第4版)(评注版)  (美)埃克尔(Eckel, B.)著 刘中兵评注 ISBN 978-7-121-13521-7 2011年6月出版 定    价:108.00元 ...

  9. 编程_三大编程思想:POP、OOP、AOP

    文章目录 三大编程思想 POP:面向过程编程 优点: 缺点: OOP:面向对象编程 1.抽象性: 2.封装性: 3.继承性: 4.多态性: 优点: 缺点: AOP:面向切面编程 优点: 缺点: 总结 ...

  10. Rxswift学习之(一)函数响应式编程思想

    Rxswift学习之(一)函数响应式编程思想 1. 函数响应式编程思想必备基本概念简介 2. iOS中三种编程思想:链式.函数式和响应式编程 2.1 链式编程 2.2 函数式编程 2.3 响应式编程 ...

最新文章

  1. 复旦邱锡鹏教授公布《神经网络与深度学习》,中文免费下载 | 极客头条
  2. Elasticsearch之深入了解Doc Values 和 Fielddata
  3. np.c_和np.r_用法
  4. ES6常用知识点概述
  5. Jobdu MM分水果
  6. DL之AlexNet:利用卷积神经网络类AlexNet实现猫狗分类识别(图片数据增强→保存h5模型)
  7. java boxplot_Matlab Boxplots
  8. SpringCloudGateway静态路由配置
  9. WebStrom Sass 编译配置 windows
  10. python 修改图片尺寸_python 批量修改图片大小
  11. LeetCode 1042. 不邻接植花(图的数据结构)
  12. 神仙在双11晚上,都干了些啥?
  13. 雪豹玩家必备网站推荐:
  14. 小鹿线前端课程怎么样
  15. 信息差、技能差、资源差、认知差
  16. CIO40: IT中年男修身修性修心之王阳明
  17. model.compile
  18. 前端进阶知识汇总(持续更新中)
  19. 《深入浅出数据分析》R语言实用教程
  20. 移植OpenHarmony到星空派ARM芯片【1】

热门文章

  1. 步骤一:支付宝-查看PID和APPID信息步骤
  2. python爬取豆瓣电影top250网络响应_python使用requests+re爬取豆瓣电影top250简单入门爬虫...
  3. DP 动态规划(一) ——背包问题 学习总结(闫氏DP分析法)
  4. 第二章:上下文无关文法
  5. 树莓派默认登录账号密码
  6. 百度网盘文件转存到阿里云盘工具,爱死这个软件了
  7. 前端开发过程中经常遇到的问题以及对应解决方法 (持续更新)
  8. CISP-PTE考试介绍
  9. 动态壁纸安卓_抖音新款“八卦罗盘”屏保,苹果安卓都能用!
  10. 洛谷试炼场 普及常见模板