对于非软件开发者,编程是什么样子?多大程度上能理解?

2021-01-28 14:31:23 +08:00
 sillydaddy

我比较好奇,对于非软件开发者,编程是什么样子?他们在多大程度上能理解开发者的工作? 也许开发者对编程太熟悉,已经忘了庐山在身外者眼中的面目。

我说下自己的想法,猜想一下编程为什么难以被普通人理解,以及怎样解决,解决了又有什么好处。

计算机世界的特性

计算机虽然有看得见摸得着的实体,但它的原理仍然是非常抽象的(毕竟它几乎无所不能啊)。

  1. 硬件方面:内存,寄存器,总线,时钟,中断,处理器等等。
  2. 软件方面:汇编指令,数据结构,操作系统,线程,进程,编程语言等等等等。

虽然人人能处理像“父母,亲戚,朋友,水果,箱子,变化,值”等数不清的抽象概念,但计算机软硬件的概念,明显不是普通人会遇到的。

计算机的底层是指令级的精确。程序就是一条条精确的指令的集合。计算机执行指令的过程,就如同一个鼠目寸光的人,取过一条指令,根据指令的内容,作出非常非常精确的动作,绝不增减。

这个指令,在不同的层级,可以有不同的抽象,

  1. 在非常底层的层面来说,就是操作内存、寄存器、驱动器等等,
  2. 对于编程语言来说,似乎稍微好一些,变成了操作某个数据结构。
  3. 而对于应用层面,一个函数调用指令,可能会完成复杂的计算,发送一大串数据,绘制出完整的图形。

但不管是哪一个层级,指令仍然是精确的。上层的指令看起来比底层更复杂强大,只因它封装包含了更多的底层指令。

举例来说,应用层的一个对一组数排序的指令,包含的是编程语言层的操作数组元素、比较数大小、循环等很多指令的组合,对应的计算机底层则是更多的内存读写,寄存器读写等指令。

这种对精确性的苛刻要求,对于普通人来说,无疑是一个迥异的思维模式(开发者就见多不怪了)。

对普通人的困难

对于抽象性来说,

一般来说,越上层的抽象越容易理解。像是 UI 组件、应用层 API 这些上层的抽象概念,尽管也是计算机世界的抽象,但对于普通人来说,毕竟不像天书了。但仅仅理解这些,对于理解计算机的工作原理,甚至对于理解开发人员的日常工作,也是不够的。因为大多数的开发工作,至少要熟悉编程语言层面的抽象概念,比如循环、判断、数组、字典、变量、取值、赋值、函数、类,甚至协程、线程、进程、消息、同步、异步等等。对于普通人来说,这些抽象概念就比较复杂了。

对于精确性来说,

假设普通人已经理解了编程方面的抽象概念,也能够通过上述的概念来操纵编程语言了。他还是要面临接下来的困难:怎样把一件由现实抽象而来的任务,从上层的抽象,逐级精确的分解为他掌握的编程语言指令。

仍以给一组数排序作为例子,在明白了 for 循环,if/else 判断,明白了数组,明白了怎样读写数组里面元素,明白这些抽象概念后,怎样完成排序这一任务呢?

因为对于普通人来说,排序是毋庸置疑的简单,显而易见的容易。但恰恰是这个“显而易见”,让他感到分解任务到编程语言的指令时,出现了困难。由模糊的“显而易见”到“精确指令”是他难以跨过的一道门槛。

其实不止是普通人,即使是开发人员,在写代码时,仍然会为边界条件而犯愁。明明知道程序的基本逻辑是对的,但如果各种边界条件处理不对,精确无比从而“挑剔”无比的程序就会“罢工”。

解决办法

那么怎样解决“抽象性”和“精确性”这 2 个难题呢?

仍然以一组数的排序为例,假设使用冒泡方法来排序,则会用到数组、获取数组长度、数组元素读取、数组元素修改、变量、数的比较操作、循环结构这 7 个抽象概念。

为了解决抽象性,需要把这几个概念具象化和可视化。现在想象在一个计算机模拟的具象化三维世界中,学习编程的人,作为用户,要在这个具象化的世界中,完成排序的任务。他可以具象化地操作这个世界里面的具象物体。

为了解决精确性,需要在这个具象化的世界里,尽可能隐藏所有具象物体暴露出的信息,减少不必要的可见信息对用户的干扰,迫使他使用指令去获取。比如对于具象化为一排箱子的数组,数组里面数的内容应该是隐藏的,数组的长度信息也应该是隐藏的。用户只有使用指令才能获取。这样迫使用户在解决问题时,必须使用编程思维,而不是利用视觉思维。

其他指令的具象化,也需要注意,比如获取数组的长度,怎样具象化这个指令呢?获取的长度信息又要放在哪里呢?应该是放在一个变量里,因为获取长度信息,不是让用户去看的,而是为了给后续的指令来使用的。

还有不少抽象概念需要具象化,目前我还没有想清楚。

理解程序开发和程序开发者

当用户在这样一个把所有编程世界的抽象概念都具象化了的环境中时,他不需要去考虑那些编程的概念,所有的概念都具象化为类似现实世界的事物。而当他在这样一个虚拟的“现实世界”中找到了问题的解法,那么简单变换,就直接得到了对应的程序。

更重要的,他已经是在使用编程的思维了。

最重要的是,他理解开发人员的工作了。世界上又多了一份理解,多么美好。

4346 次点击
所在节点    奇思妙想
25 条回复
lewis89
2021-01-28 17:48:32 +08:00
因果一致性,吃饭 拉屎 擦屁股, 吃饭 拉屎 擦屁股
shendaowu
2021-01-28 17:51:05 +08:00
用 Brainfuck 向外行介绍编程?也许是个馊主意。
MakeItGreat
2021-01-28 17:53:16 +08:00
就和英语美术音乐体育这些一样
小时候学习快,长大了就慢了
opengps
2021-01-28 17:53:51 +08:00
外行人就不用解释那么准确了,相信我。你就说你是修电脑的,而且是啥也不会那种菜鸟,他们保证一听就懂
superliwei
2021-01-28 19:25:59 +08:00
不要尝试让别人理解,除非你欠他钱。
orannge
2021-01-28 19:40:12 +08:00
这是入行的理解,看电影需要理解演员的工作吗?人与人的理解就两个字,尊重。
namelosw
2021-01-28 19:55:58 +08:00
其实应该反过来, 程序员要让自己的代码更抽象. 但是大部分程序员做得并不好.

比如你说的数组长度, 正常人的思维就是长度, 就是直觉:
list.length

如果你追问, 那么他们可以把直觉分解开, 搞得更具体一些:
list.map(() => 1).sum()

再更具体一些:
list.map(() => 1).reduce((x, y) => x + y, 0)

普通程序员的思维:
while
namelosw
2021-01-28 19:59:52 +08:00
不小心按快捷键发出去了, 接上:

普通程序员的思维
let sum = 0
while (...) {...}

所以写得更函数式或者更逻辑式一些, 反而和普通人的思维比较接近, 比如可以思考一下:
三角形三边长度都是整数, 三边之和长度小于 N, 一共有几种组合, 分别用 C 和 Haskell 写有什么不同
cmdOptionKana
2021-01-28 20:26:27 +08:00
具体是什么人不理解? 80 、90 、00 后对电脑和手机已经很熟悉了,如果对编程或程序员这个职业有一点兴趣,应该不难理解。

如果是对这方面没有兴趣的人,不管你怎么解释,他们也听不进去呀。

很多人所谓的不理解,要么是漠不关心,要么是有偏见(多数对这个职业没偏见,而是对具体人的有偏见,不管他是什么职业,都会无意或故意说几句那个职业的误解来调侃)。

不是难理解,多数人是没有去理解的意愿。
hxndg
2021-01-28 22:39:22 +08:00
从某种意义来说,程序员实际上提供的是一种有序的抽象。

但是从工作来说,程序员提供的是各种各样的补偿操作,要么牺牲这个换取那个,要么牺牲那个换取这个。

所谓的精确,很多时候都是无稽之谈。现代计算机并行体系并不保证你看到的就是稳定的结果,换言之提供地是一种承诺。只承诺什么是绝对不会出现。

至于对计算机而言,从本质来说是一堆一堆的协议套起来的。
favourstreet
2021-01-28 23:06:31 +08:00
Dijkstra 老师有句活:If debugging is the process of removing bugs, then programming must be the process of putting them in.

编程没什么神秘的,调试 Debug 才是开发人员真正的工作。教会一个普通人编程是很快的,但是学会 debug 却必须对计算机有通透的理解。
AmrtaShiva
2021-01-29 08:11:02 +08:00
理论说的天花乱坠 不如动手实战 做过了才能说有所理解
no1xsyzy
2021-01-29 11:07:48 +08:00
@namelosw 手动 @excel,大部分人的第一门函数式编程语言。
namelosw
2021-01-29 11:52:22 +08:00
@no1xsyzy 对, excel 就是个例子, 以等式为核心的.

像上面说的三角形, 用 Haskell 是 [ (a,b,c) | c <- [1..n], b <- [1..c], a <- [1..b], a^2 + b^2 == c^2, a+b+c < n]

其实概念上就是几个类似的等式 /不等式拼起来, 只描述需求, 不说求值过程, 感觉上和用 Excel 就很像:
c < n
b < c
a < b
a^2 + b^2 == c ^2
a + b + c < n

这样的话, 和各种 for 循环检测 break, 挨个元素 push 进数组感觉上完全不一样了, 和大部分人的思维比较接近一些.
sillydaddy
2021-01-29 12:16:55 +08:00
@no1xsyzy
@namelosw
为啥我看不懂你们讨论的东西。。

@namelosw
你说的这个三角形的问题,让我回忆起了在学校了解过的 Prolog 语言,看起来就是在描述问题。但是 Haskell 这种函数式编程语言也能做到吗? 现在想想这种语言还真是神奇。

为啥我感觉 C 语言式的过程编程,也比较符合人的思维? 这个三角形的问题交给普通人来手算,他想出的解法应该也是分步骤的吧。
namelosw
2021-01-29 12:59:53 +08:00
@sillydaddy


> 你说的这个三角形的问题,让我回忆起了在学校了解过的 Prolog 语言,看起来就是在描述问题。但是 Haskell 这种函数式编程语言也能做到吗? 现在想想这种语言还真是神奇。

函数式语言(其实不一定函数式语言, 普通语言有个语法糖就行)只能做到一小部分这种效果, Prolog 是对离散的问题都可以做到这种效果(但不保证停机). 现在的深度学习有点像一个积分版的 Prolog, 不只能解离散问题(王垠的博客里也提过这个观点).

实际上上面三角形的问题那个语法糖都是 Monad 和 Applicative 的变种. 有点类似于 JS 的 Promise.then 和 Promise.all. 或者列表的 map 和 flatMap 方法组合.

[ (a,b,c) | c <- [1..n], b <- [1..c], a <- [1..b], a^2 + b^2 == c^2, a+b+c < n]

约等于

do
let c <- [1..n]
let b <- [1..c]
let a <- [1..b]
guard $ a^2 + b^2 == c ^2
guard $ a+b+c < n
return (a, b, c)

中间还能脱糖一步, 就是变成>>= (flatMap / bind)和. (fmap / map)就跳过了, 下一步脱糖成类似 JS 的伪代码:

[1..n].flatMap(c => {
[1..c].flatMap(b => {
[1..b].map(a => {
return [a, b, c]
})
})
}).filter(([a, b, c]) => a^2 + b^2 == c^2)
.filter(([a, b, c]) => a + b + c < n)

SICP 里面第二次解八皇后问题就是类似这样的 flatMap/map 嵌套, 跟第一次解比明显可读了很多. 这种嵌套模式巨常见, 不仅用在列表上, 还能用在 async, optional, stream 等等各种东西上, 所以很多语言都有语法糖.

其实 JS C#的 async await, C#的 LinQ, Scala 的 for, Rust/Swift 的?本质上都是这个语法糖, 实际的变换都是把看起来像一个变量声明套到一个类似 lambda 的东西里做参数嵌套, 前后前几步都是 flatMap, 最后一步变成 map.

这样其实就是一个很抽象的描述让计算机自己分解成具体过程的例子. Prolog 和深度学习就更高级一些, 干脆只写名字不写函数体直接调用, 给定 Facts 和 Rules 直接问结果, 所谓的“函数”都是电脑自己生成的.

> 为啥我感觉 C 语言式的过程编程,也比较符合人的思维? 这个三角形的问题交给普通人来手算,他想出的解法应该也是分步骤的吧。

但是普通人不用分解, 或者不想分解. 他们的期望在高抽象的环境下工作. 比如产品经理或者老板, 他们的想法其实就是 wishful thinking, 只要逻辑上说得通, 实现只是细节, 那么细节其实就交给程序员了, 程序员就是他们的计算机.

理想情况下, 如果程序员能把自己的工具抽象得很好, 其实就减少了工作, 聊聊数句把 specification 以严谨的语言告诉计算机就可以了.
php01
2021-01-29 13:03:30 +08:00
编程很简单,但是总有人为了展示自己所了解的,将这东西说得天花乱坠无比复杂,从而体现自己那虚无的满足感甚至是优越感。
这就相当于一个三岁的小朋友问你什么是数学,你跟他聊微积分并且说这是基础,不懂这玩意,你就不懂数学,只能做个简单的计算处理工作,没出息,低端,以后活该被卷。
这事是不是很离谱。但是放到编程这一块,让一些人跟外行解释这是干嘛的,这就是常态。
我想对这些人说,21 世纪了,自信点。
php01
2021-01-29 13:06:20 +08:00
三岁小朋友,刚开始你只用教他 1-99 就行了。0 都没必要教,只要教他 100 最大就行了。甚至不用会写,只用从 1 数到 20 就行了,都不需要一直写到 99,因为后面只是重复。我相信我们都是这么长大的,循序渐进。到这里,上来就是高等数学,上来就是算法导论,干嘛啊。
no1xsyzy
2021-01-29 13:31:30 +08:00
@sillydaddy
@namelosw
这其实是 top-down 和 bottom-up 两种形式,具体展开就是哲学认知论的范畴了。
这点,大概可以参考下 pandoc 是怎么写的(毕竟作者是哲学教授还主攻认知论方面
BingoXuan
2021-01-29 13:35:45 +08:00
我见过最简单的方法去理解就是表格( checklist ),从第一项开始写,你需要干什么写什么,程序会自动一一执行,只要跑到最后就是完成。所以楼上以 excel 举例其实是 ok 的,但 excel 对于更普通的人来说还是太难理解。

这是一个专为移动设备优化的页面(即为了让你能够在 Google 搜索结果里秒开这个页面),如果你希望参与 V2EX 社区的讨论,你可以继续到 V2EX 上打开本讨论主题的完整版本。

https://www.v2ex.com/t/749227

V2EX 是创意工作者们的社区,是一个分享自己正在做的有趣事物、交流想法,可以遇见新朋友甚至新机会的地方。

V2EX is a community of developers, designers and creative people.

© 2021 V2EX