软件工程 1:软件危机_软件工程危机 具象-程序员宅基地

技术标签: C/C++  

软件工程第一课摘要

 


软件工程

编程是个非常适合自学成才的项目,我就是自学的。

很多人和我一样不是科班出身,自学编程技术,也容易找到一个程序员的职位,甚至还可以自己开发一个小软件。

但仅限于 小 软件,比如您可以自己写一个电子邮件客户端程序,或者写一个视频编辑工具。

可是如果要开发一个超大型软件,其中涉及到的学问,可就不是自学所能达到的了,那是需要在重大项目的实践中去领悟和提高的。

自学也许可以让您成为一个优秀的侠客,而伟大的将帅,则只能用千万士兵的鲜血铸就。

在计算机科学里,软件工程这一部分,对计算机科学家来说太难了。

不了解软件工程,您就不知道什么叫“大”,什么叫“复杂”。

中国有很多这样的厉害人物,是手机 APP 开发大国,有很多超大型企业,有全世界最长的跨海大桥,却没有没有属于自己的计算机操作系统、国产芯片…

因为这些事儿,跟现代软件工程相比,还只能算是简单的事儿。

现代主流操作系统,包括 Windows, Mac 和 Linux,各自都有接近一亿行代码,而且大致 确保了不出问题(其实有五个方面的要求,不过简单起见总结为一个)。

代码每多一个量级,维护难度系数会不呈比例的指数上升。

汉朝的时候,是8000个人养一个公务员;唐朝,3000个人养一个公务员;明朝2000人养一个;到了清朝是1000人养一个公务员 —— 而今天的中国,则是18个人养一个公务员!

大了、就是不一样。

我研究了身边一些很聪明的人,发现他们聪明是因为工具很多,一个工具不行就换一个,所以解决问题会更多、会更好。

如果您只会两个视角,那您就只有一对连接。而如果您会5个视角,理论上您一共可以有 5×4/2 = 10 个连接 —— 相当于五个点两两之间都连一条线:

您要是有 10 个视角,就可以有 10×9/2=45 个连接。

因为视角的这个超加性,多样性的好处会不成比例的增加。

这个工具其实是思考工具,像哲学家、科学家这方面的工具特别的多。

那么我们再面对一个问题时,我们能否也变得像TA们一样的聪明???

当然可以啦,思想可以学习,方法可以模仿。

工具随时可以获取。比如,我喜欢读一些神作,他们不仅读的爽,还有一个行业的底层逻辑。

神作 底层逻辑 类型
图论 多对多的网络关系 计算机课程
线代 一组数字研究世界 计算机课程
经济学 国师问道 商科
金融 百姓之道 商科
绝命毒师 完整的毒品犯罪链 电影
亿万 对冲基金的运作原理 电影
心理学 自信+热情 通识教育
亲密关系 爱的能力 通识教育

长期下来,越来越多样化,视角、意趣都多了很多。积累到了一定程度,就发现,多了就是不一样。

而软件工程的底层逻辑,可以说是工程管理和综合治理手段的极限。

小软件和大软件的根本区别在于尺度,以前一个小软件只有几千行代码,现在一个大软件要有几百万行代码。

以前的软件是给一个人用,现在是多个用户共同使用一个软件;更重要的一点是,以前的软件是一个人或者几个人开发的,现在则是大型团队一起开发。

计算机思想家弗瑞德里克·布鲁克斯(Fred Brooks),曾经在上世纪六十年代末率领 IBM 公司 300 人的团队开发操作系统。

他做完这件事之后很有感触,为此专门写了一本书,叫《人月神话》。

布鲁克斯提出两个感慨:

  • 1 个人干 12 个月的活,绝对不是 12 个人在 1 个月内能干完的。项目用的程序员越多,平均每个人出活的速度就越慢。所以您规划项目的时候不要算什么“人月”。
  • 您这个团队做出来的软件的结构,往往和您这个团队的人员组织管理结构高度相似。 所以软件工程不但要管项目,还要管人。

布鲁克斯这本书出来,人们才充分认识到软件工程的难度。

 


面向对象与面向过程

面向过程:OOP,分析问题的解决步骤,而后用 函数 把步骤按顺序一一实现并调用即可。

面向对象:POP,把构成问题的事务分解为各种对象,而建立对象的目的不是为了完成一个一个的步骤,而是描述某个事务在解决整个问题过程中发生的行为。

对于刚刚学完 C 的小白来说,面向对象的思想和思想可谓有点复杂。

如果把 俩个思想 “类比” 到一句话里面,异同就会十分明显。

另外,我习惯英文缩写,这样传递的信息十分简短方便,全称百度。

e.g. 下雨的时候,人们为了防止被雨淋湿打开了雨伞️。

面向过程解析:

  • 过程是:下雨了,打开伞,挡雨。过程都是动词哦。

  • 编码实现:fall(),open(),prevent(),这 3 个函数一一对应上行的步骤如 fall() 代表下雨。

面向对象解析:

  • 对象:我 、伞、 雨,都是名词。
  • 编码实现:me,umbrella,rain。对象都是名词呀。

对象有自己的行为:我可以打开伞、伞可以挡雨、雨可以蹦极。

再以实际情况安排对象行为的顺序:雨下,我打开伞,伞挡雨。

  • 编码实现:rain.fall(),me.open(),umbrella.prevent()

因此,面向过程是 把问题分解为若干个步骤,每个步骤实现为一个函数,按照顺序实现并在调用时传递数据给函数解答问题。

面向对象是 抽象出问题的各种对象,把数据和解决问题的方法封装在对象中,而后各个对象之间通过行为实现解答问题。

练习:试着用面向对象的思想重写下图:

 


软件危机

早期的编程语言,如 汇编语言、只有0和1的机器语言,本质上是面向机器编程。

那个时代里,活着的年轻人们重新思考了软件编程的认知。

他们开始认为编程的设计应该以人为本,开发了许多比较符合人类习惯和逻辑思维的语句。

就是CPU的指令集,要想让CPU工作,必须借助特定的指令。

  • add 用于加法运算
  • sub 用于除法运算
  • cmp 用于比较两个数的大小
‌mov  ptr[a], 0X14
mov  ptr[b], 0XAE
mov  eax, ptr[a]
add  eax, ptr[b]
mov  ptr[c], eax

但CPU指令集(汇编语言)还是比较抽象,人们有了一个自然的需求,能不能按照人容易理解的思维写程序后把写出来的程序自动翻译成机器语言呢 ?

后来,计算机科学家们发现所有程序可以化为三种结构构成:顺序结构、分支结构和循环结构。

  • 如果…就… if…else
  • 循环 while
  • 去哪里 goto
if ( 想明白了么 )
	printf("没想明白,什么好吃吃一点,什么好玩玩一点,挺OK。");
else
	printf("想明白了就干!!虽然我们大多不是科班出生,但只要思想没有被束缚、学习更加主动且积极的面对问题,在每一次小成功中积累,让量变引发质变,我们会有很大概率成为自己想成为的人。");

这就是所谓高级编程语言,正是这使他们摆脱了对计算指令的束缚,使用人类语言代替了机器语言。

这样的语言关注逻辑处理过程,所以也被称为面向过程、面向人的、面向程序员的编程语言,比如 Fortran、C。

高级编程语言的普及极大地释放了程序员的自主性,软件开发迎来黄金时期,程序员的第一个极客时代到来,比尔·盖茨、乔布斯都是在那个时代成长起来的。

他们将常用、好用的代码 封装 起来,重复使用。编程语言的库函数具有标准化的输入和输出,程序员下次再用的时候只需要照顾好输入输出,而不必关心函数内部是什么情形 —— 这就能大大降低出错的概率和提高编程的效率。

1957 年,Fortran 语言被发明了,这是一个科学计算语言,特点是特别容易写公式。

1958 年,LISP 语言出现,这是一个极其强大的符号处理和逻辑运算语言,甚至可以用于人工智能设计。

1959 年,人们又发明了 COBOL 语言,用于商用数据库编程。

要方便人们在一台计算机上操作,您就得有账号管理,得安排不同的程序同时运行,那么就得有操作系统,程序员就得有系统思维。

要想开发出来的软件好用、可靠、容易维护,程序员就得有工程思维。

接下来还有了互联网,程序员就需要网络思维和安全思维。

再进一步,编程思想也在演化。

传统编程语言是线程式的,程序员思维模式是操控计算机。

但是人的欲望是没有止境的,人能做到的越多,想得到的也就越多,越来越庞大的软件开发计划被不断地提了出来。

可面向过程的复杂性随着软件规模的膨胀以更快的速度膨胀(超加性)。

面向过程的软件关注逻辑流程,更容易被设计成面条式程序,长长的过程调用执行,像一根面条。

而大型项目最后由这样一根一根面条组成,就成了一个毛线团,最后谁也理不清了。

于是很多大型软件的开发过程开始失控,最终以失败告终,人们遇到了软件危机。

软件工程的问题不是每年能培养多少高水平程序员的问题,而是复杂性问题。

软件危机使人们开始重新审视软件编程这件事情的本质,除了一部分科学计算或者其他特定目的的软件,大部分的软件是为了解决现实世界的问题,企业的库存管理、银行的账务处理等等。

所以,软件编程的本质是程序员用代码的方式使现实世界的事务运行在计算机上,计算机软件是为了解决现实世界的问题而开发出来的,那么软件编程这件事情应该关注的重点是客观世界的事物本身,而不是程序员的思维方式或者计算机的指令。

如果软件编程的重点是客观世界的事物本身,那么编程语言如何才能更好地满足这一需求?

于是,面向对象的编程语言应运而生。

面向对象编程以对象作为软件编程的基本单位,提出一切皆对象,客观世界的用户、账号、商品是对象;创建、组合、关联这些对象的工厂、适配器、观察者也是对象;将所有这些对象分析、设计、开发出来,一个软件系统就完成了,这个软件系统灵活、强大,最重要的是可以根据需求变化快速更新维护

面向对象编程似乎已经进化到编程这件事情哲学意义上的终点,是编程语言的终极形态。

现实看起来也确实如此,最近三十年诞生的编程语言几乎全部都是面向对象的编程语言,面向对象一统天下。

但事实真的如此吗?

回望历史我们站在上帝视角,一切都是如此清晰充满条理,凝望未来,我们还能如此笃定吗?

情况也许并非如此。

事实上,现实中的面向对象编程几乎从未实现人们期望中的面向对象编程。

这有人的原因,也有编程语言的原因…

而随着科技的不断发展,特别是大数据,人工智能以及移动互联网的发展,面向数据的编程需求越来越多,能够更好迎合这一需求的编程模型开始得到青睐,比如函数式编程。

而极客型的程序员对强类型的面向对象编程越来越不感冒,他们希望在编程的时候能够得到更多的自由,编程语言的重心似乎重新出现面向程序员的趋势。

随着计算机性能的不断增强,以及互联网应用对计算资源需求的不断增加,如何更好地利用 CPU 的多核以及分布式集群的多服务器特性,必须是软件编程以及架构设计时需要考虑的重要问题,软件编程越来越多需要考虑机器本身,相对应的,反应式编程得到越来越多的关注。

我们都在时代里,而时代是在螺旋式的上升…

P.S. 其实不止 C++、Python、java 等编程语言可以实现面向对象的机制,C 语言一样可以,在 Linux 内核源代码里应用广泛啊。如果有想法,可以看看《Object-Oriented Programming With ANSI-C》(用C实现面向对象的各种机制)。

 


中间层抽象与具象化类比

在计算机中,为了让操作更加直观、易于理解、增强用户体验,开发者经常会使用一件法宝——增加中间层,即使用一种间接的方式来屏蔽复杂的底层细节,只给用户提供简单的接口。

实际上,计算机的整个发展过程就是不断引入新的中间层:

  • 计算机的早期,程序都是直接运行在硬件之上,自己负责硬件的管理工作;程序员也使用二进制进行编程,需要处理各种边界条件和安全问题。

  • 后来人们不能忍受了,于是开发出了操作系统,让它来管理各种硬件,同时发明了汇编语言,减轻程序员的负担。

  • 随着软件规模的不断增大,使用汇编语言编程开始变得捉襟见肘,不仅学习成本高,开发效率也很低,于是C语言诞生了。C语言编译器先将C代码翻译为汇编代码,再由汇编器将汇编代码翻译成机器指令。

  • 随着计算机的发展,硬件越来越强大,软件越来越复杂,人们又不满足于使用C语言了,于是 C++、Java、C#、PHP 等现代化的编程语言诞生了。

从具象到抽象化并传承这些抽象的知识、经验,是人与其他动物最大的区别

一个领域的知识如果不断地深入发展,都有同一个趋势,那就是从具象化到抽象化。

作为程序里,我们经常要使用:类、抽象类、接口 这些抽象概念。

进步想,程序本身也是对现实世界的抽象。

程序可以实现对现实世界的高度模拟,制造出许多的“世界”。

再进一步,我们所在的现实世界也无法被自然语言精确描述。

作为普通人,想要更精确的理解世界,抽象思维是不可或缺的。

首先,抽象思维能让您认识到事物的本质。

高手,要善于发现各种看似不一样的事物背后的共同点。

而后使用类比,对现实的抽象,抽象的好,就形成了事物的模型。然后,匹配模型。

从前医生们面对一个问题,束手无策。

有一种射线,只要以一定的强度照射在肿瘤上,就能把肿瘤给杀死,等于是可以用来治疗癌症。 现在问题在于,射线到达肿瘤之前肯定会先接触到患者身体的其他组织,那就会把好的组织也给杀死。 可是如果把射线强度调低一点,好的组织能不被伤害,可是对肿瘤就也没用了。 那有没有一个什么办法,不用做手术开刀,既能让射线杀死肿瘤,又不会伤害其他组织呢?

就设计而言,这个答案本身并不重要,我们关心的是寻找答案过程中使用的思维方式。

这个方法就是 “类比”,用类比解决问题,是把一个领域的思想,运用到另一个领域中去。

分享一个故事:

从前有一个将军,要攻打一座城。 攻城需要很多士兵同时发动进攻才好。 可是这座城周围的道路都很窄小,并不适合大军通过。 这怎么办呢? 将军知道通往这座城的道路有很多条,于是他把士兵分散开,以小队的形式从不同的道路出发,按照约定时间一起到达。 结果就把城给攻下来了。

类比解决问题,是把一个领域的思想,运用到另一个领域中去。

上面答案是用若干束低强度的射线从不同的方向照射肿瘤。

因为射线强度不高,所以不会杀死途中路过的身体组织;而因为在肿瘤上汇聚的多个射线加起来的强度够高,所以能杀死肿瘤。

这个原理就好像用放大镜汇聚太阳光一样……

其实这就是现在有不少医院使用的“伽马刀”。

那么,如何类比?

一般人看东西是关注不同点,而高手则善于发现两个很不一样的事物之间的相同点。

比如,下面这六件事情,您能不能把它们给分个类 ——

  • 经济泡沫
  • 北极冰川融化
  • 美联储调节利率
  • 人的身体出汗
  • 不同的商品相继涨价
  • 大脑指挥身体做动作

对美国西北大学的学生测试表明,如果是按照学科分,所有学生都能分的很好。

1、3、5 是经济学问题,4、6 是生理问题,2 是自然环境问题。

但要是按照这些事情的内部机制分类,就只有少数有跨界学习经历的学生能分好。

  • 事实上 1 和 2 都是正反馈现象(买东西的人越多经济越好,经济越好买东西的人越多;
  • 冰川越融化吸收阳光越多,吸收阳光越多冰川越融化),
  • 3 和 4 都是负反馈现象(美联储加息防止经济过热;皮肤出汗防止身体过热),
  • 5 和 6 都是连锁信号传递(石油涨价导致日用品涨价;大脑神经信号传递到四肢)。

能看出这种深层思维结构,才谈得上举一反三。

类比的就一定对吗?

类比有可能犯错误,引起争议 —— 用诸葛亮教育刘禅的话说,就是“引喻失义”。

类比思维的规律是,您能想到的类比越多,您的判断就会越准确;您能想到的类比越遥远,您出的主意就会越有创造性。

高手听人讲什么东西的时候,会在头脑中画一个东西:您一说四根柱子,他就画了一座大楼。您继续讲更多的内容,他就不断调整和补充头脑里这个东西。您讲完了,他就会发现这个东西哪里似乎不怎么平,哪里似乎还没完成,哪里似乎还可以往外延伸,哪里似乎可以跟他熟悉的什么东西连接起来,他还可能发现整个这个东西跟另一个东西很像。他眼中简直到处都是问题。

说白了,这也是类比和联想。

总之,类比是一个非常有用的思维方式。

在思维方法层面,具体分为:

  • 具体类比:以事件之间具体特征相比,寻找新理解;
  • 情感类比:将事物人格化,在感性层突破习惯认知,提炼新方法;
  • 抽象类比:在词语和概念维度相比,极易出错,以高层原则维护;
  • 非现实类比:借幻想和超现实概念与现实问题相融,升级认知;如三体衍生术语。

类比可以让我们举一反三,类比可以启发我们创造新事物,类比可以让我们审视自己和别人的原则,类比可以帮助我们发现各方的分歧所在,类比可以帮助交流思想……类比的背后,是高级的抽象思维。
 


复盘:

版权声明:本文为博主原创文章,遵循 CC 4.0 BY-SA 版权协议,转载请附上原文出处链接和本声明。
本文链接:https://blog.csdn.net/qq_41739364/article/details/104870224

智能推荐

c# 调用c++ lib静态库_c#调用lib-程序员宅基地

文章浏览阅读2w次,点赞7次,收藏51次。四个步骤1.创建C++ Win32项目动态库dll 2.在Win32项目动态库中添加 外部依赖项 lib头文件和lib库3.导出C接口4.c#调用c++动态库开始你的表演...①创建一个空白的解决方案,在解决方案中添加 Visual C++ , Win32 项目空白解决方案的创建:添加Visual C++ , Win32 项目这......_c#调用lib

deepin/ubuntu安装苹方字体-程序员宅基地

文章浏览阅读4.6k次。苹方字体是苹果系统上的黑体,挺好看的。注重颜值的网站都会使用,例如知乎:font-family: -apple-system, BlinkMacSystemFont, Helvetica Neue, PingFang SC, Microsoft YaHei, Source Han Sans SC, Noto Sans CJK SC, W..._ubuntu pingfang

html表单常见操作汇总_html表单的处理程序有那些-程序员宅基地

文章浏览阅读159次。表单表单概述表单标签表单域按钮控件demo表单标签表单标签基本语法结构<form action="处理数据程序的url地址“ method=”get|post“ name="表单名称”></form><!--action,当提交表单时,向何处发送表单中的数据,地址可以是相对地址也可以是绝对地址--><!--method将表单中的数据传送给服务器处理,get方式直接显示在url地址中,数据可以被缓存,且长度有限制;而post方式数据隐藏传输,_html表单的处理程序有那些

PHP设置谷歌验证器(Google Authenticator)实现操作二步验证_php otp 验证器-程序员宅基地

文章浏览阅读1.2k次。使用说明:开启Google的登陆二步验证(即Google Authenticator服务)后用户登陆时需要输入额外由手机客户端生成的一次性密码。实现Google Authenticator功能需要服务器端和客户端的支持。服务器端负责密钥的生成、验证一次性密码是否正确。客户端记录密钥后生成一次性密码。下载谷歌验证类库文件放到项目合适位置(我这边放在项目Vender下面)https://github.com/PHPGangsta/GoogleAuthenticatorPHP代码示例://引入谷_php otp 验证器

【Python】matplotlib.plot画图横坐标混乱及间隔处理_matplotlib更改横轴间距-程序员宅基地

文章浏览阅读4.3k次,点赞5次,收藏11次。matplotlib.plot画图横坐标混乱及间隔处理_matplotlib更改横轴间距

docker — 容器存储_docker 保存容器-程序员宅基地

文章浏览阅读2.2k次。①Storage driver 处理各镜像层及容器层的处理细节,实现了多层数据的堆叠,为用户 提供了多层数据合并后的统一视图②所有 Storage driver 都使用可堆叠图像层和写时复制(CoW)策略③docker info 命令可查看当系统上的 storage driver主要用于测试目的,不建议用于生成环境。_docker 保存容器

随便推点

网络拓扑结构_网络拓扑csdn-程序员宅基地

文章浏览阅读834次,点赞27次,收藏13次。网络拓扑结构是指计算机网络中各组件(如计算机、服务器、打印机、路由器、交换机等设备)及其连接线路在物理布局或逻辑构型上的排列形式。这种布局不仅描述了设备间的实际物理连接方式,也决定了数据在网络中流动的路径和方式。不同的网络拓扑结构影响着网络的性能、可靠性、可扩展性及管理维护的难易程度。_网络拓扑csdn

JS重写Date函数,兼容IOS系统_date.prototype 将所有 ios-程序员宅基地

文章浏览阅读1.8k次,点赞5次,收藏8次。IOS系统Date的坑要创建一个指定时间的new Date对象时,通常的做法是:new Date("2020-09-21 11:11:00")这行代码在 PC 端和安卓端都是正常的,而在 iOS 端则会提示 Invalid Date 无效日期。在IOS年月日中间的横岗许换成斜杠,也就是new Date("2020/09/21 11:11:00")通常为了兼容IOS的这个坑,需要做一些额外的特殊处理,笔者在开发的时候经常会忘了兼容IOS系统。所以就想试着重写Date函数,一劳永逸,避免每次ne_date.prototype 将所有 ios

如何将EXCEL表导入plsql数据库中-程序员宅基地

文章浏览阅读5.3k次。方法一:用PLSQL Developer工具。 1 在PLSQL Developer的sql window里输入select * from test for update; 2 按F8执行 3 打开锁, 再按一下加号. 鼠标点到第一列的列头,使全列成选中状态,然后粘贴,最后commit提交即可。(前提..._excel导入pl/sql

Git常用命令速查手册-程序员宅基地

文章浏览阅读83次。Git常用命令速查手册1、初始化仓库git init2、将文件添加到仓库git add 文件名 # 将工作区的某个文件添加到暂存区 git add -u # 添加所有被tracked文件中被修改或删除的文件信息到暂存区,不处理untracked的文件git add -A # 添加所有被tracked文件中被修改或删除的文件信息到暂存区,包括untracked的文件...

分享119个ASP.NET源码总有一个是你想要的_千博二手车源码v2023 build 1120-程序员宅基地

文章浏览阅读202次。分享119个ASP.NET源码总有一个是你想要的_千博二手车源码v2023 build 1120

【C++缺省函数】 空类默认产生的6个类成员函数_空类默认产生哪些类成员函数-程序员宅基地

文章浏览阅读1.8k次。版权声明:转载请注明出处 http://blog.csdn.net/irean_lau。目录(?)[+]1、缺省构造函数。2、缺省拷贝构造函数。3、 缺省析构函数。4、缺省赋值运算符。5、缺省取址运算符。6、 缺省取址运算符 const。[cpp] view plain copy_空类默认产生哪些类成员函数

推荐文章

热门文章

相关标签