编程的世界围绕着程序转,这是毋庸置疑的。本文的作者则提出了一个更广泛的、以系统为中心的观点,他认为“系统”才是编程的最终目标。

以下为译文:

维基百科“计算机”页面上的第二句话就提到了“程序”。我们对程序很着迷,了解如何创建程序,如何构建、运行和调试程序,如何可视化程序,选择哪个语言编写我们的程序,每个语言的类型系统和语法是什么......等等。

从表面上看,这似乎并没有错,但是这里面蕴含着一种假设,即编程的世界围绕着程序转。

如果我们的立足点是我们想“编写程序”,那么我们已经将自己局限在了某个特定的思维框架中,我们必须完整地编写一个程序,然后提交给系统,经过构建和集成,最后再运行。

但这不是有点过头了?“程序”真的是最终目标吗?我的立场是,我们需要使用以系统为中心的观点重新建立我们的目标,具体如下:

  • 系统由与我们交互的硬件和软件组成:这包括硬件设备和一些没有名字的软件实体或产物。

  • 系统展示行为:我们与系统交互,系统响应输入,产生输出(屏幕上的图像,声音等)。

  • 我们修改行为。

换句话说:

  • 系统没有展示我们想要的行为;

  • 我们“采取措施”(包括操控没有名字的软件实体);

  • 然后系统展示出我们期望的行为。

这里的“采取措施”一般情况下指的都是对系统进行编程,而这样的系统自然是指可编程的系统!程序本身是系统交互的一种类型,也许我们不应该明确地划分“对系统进行编程”和“使用系统”。

好了,废话不多说,现在我可以提出这样一个目标:

我们真正的目标是设计软件“实体”的形式和性质,而该软件“实体”即为我们在编写和使用系统时操控和创作的“可编写的基板”。

我有意将这项工作全部归结为设计的问题,在设计中处理概念和抽象的发明,而这些我们可以称之为基板。这个设计的范围非常广阔,你可以非常自由地发明各种记法、概念、工具、媒体等等,以任何方式勾勒“软件编写的虚拟世界”——但是我们必须小心地甄别所有引入的概念。

需要引入文件和文件系统吗?需要编译器、数据库、操作系统、可执行文件和操作系统进程吗?在这个空间中,所有这些计算的附属概念还都不存在,我们只有一张白纸。在这个后编程时代(或许应该叫做“前编程时代”)的思维模式中,我们该怎么处理这些自由度?

程序的思想

首先,让我们回顾一下程序的概念,但要注意程序只是对系统编程的方式之一(请注意动词“编程”和名词“程序”的区别)。

我们说“有一个叫做程序的东西”,然后继续描述这个概念是什么、如何使用等等,这通常是我们在计算机入门教材或维基百科上“程序”的页面中所能看到的内容。我们对“编程思想”已了然于心,但是我想在这里谈论有关编程思想的事情。

程序就好像程序员撰写的文章,它有自己的结构,通过一种主要的视觉表现手法呈现,程序员通过这种表现手法(即源代码)来查看并操控程序。程序包含了一次“执行”的详细步骤,这意味着它可以在某个时候“运行”,从而产生一个“运行中的程序”。请不要误解成存在一种“不运行的程序”,这里的“运行中的程序”只不过是原来的程序加上某种运行时状态而已,这些状态附着在程序的各个部分,并会随着程序的运行而改变。这就引入了两个阶段的概念——运行和未运行。程序的定义也是一种概念一般化,即程序可以拥有多个运行中的实例,每个实例的细节都不完全相同。

操作系统进程也是程序

在Unix(以及Windows和Mac)中,程序的概念通常被当做操作系统的进程。如果我们接受这种关联,将操作系统的进程看作一种程序,我们就可以继续提供更多描述性的细节。例如,当一个运行程序停止时,所有运行时的状态会被立即清除。对于长期的状态,程序可以在运行的时候修改外部状态,也就是说我们需要定义外部状态是什么,或者至少要定义内部和外部之间的耦合。

我们还需要一些编写和调用程序的工具软件,我们通过其他程序(比如编辑器、编译器、shell和GUI等)从外部操作程序。

最后,我们需要一些显示和交互的概念,运行程序通过这些概念与我们交互。通常,这就是为用户设计的“运行时的用户界面”(程序的第二种视觉表现手法)。在有些情况下,程序员同时也是用户,但这并不妨碍我们使用两种不同的表示方法。程序还可以与其他程序交互,这就涉及两个程序之间如何互相定位,以及交互本身的性质等问题。

我想说明的是,程序有一个框架,即有关程序方面的工作中常见的、不言而喻的假设。我想在这里注明以下三个方面:

1、我们需要做出很多的选择,我们可以随时决定改变方向。毕竟,这些概念都是人为提出来的。例如,我们可以选择非纯文本的方式表示所有。或者我们可以只选择一种表现手法(而不是两种——主要表现手法和第二种表现手法,即源代码和运行时的用户界面)。我们仍然能得到程序,虽然它们的工作方式不同。

2、似乎我们不能只引入一个单独的概念。概念之间相辅相成,所以我们需要引入一整套相互关联的概念。这是否意味着如果我们将“程序概念”引入另一个世界,我们就需要引入许多相关概念?可能吧,如果设计整个软件世界的话,就需要考虑这些情况。

3、程序或操作系统进程的概念可以解决的问题与不能解决的问题之间有一个界限。例如,如果我想在一个大程序内定义小程序(这个想法很合理,因为所有进程都可以分解成小进程),那么就只能自己想办法了。

想想主流操作系统的工作原理,我们还可以确定一系列的设计选择,这就可以决定包含哪些内容,不包含哪些,例如:

  • 所有外部进程的持久系统状态都以命名字节blob的方式保存在分层文件系统中,并由运行中的进程明确进行管理;

  • IPC和进程内核通信通过C语义实现成API调用;

  • 系统不提供将单个进程分成不同的部分的隔离机制;

  • 不提供保存运行进程的状态或回滚到前一个状态的机制;

  • 不提供替换正在运行的进程的某个部分的机制。

系统不提供的内容都可以由“用户空间”特定的程序解决,但核心抽象仍然可以决定常见且简单的内容。

有关“程序”的讨论够多了,让我们继续看看更有趣的几个问题:

我们是否需要将“程序”的概念引入到我们的各种软件中?在没有“编程思想”的情况下,我们能否拥有一个可编程的系统?

没有程序的编程

这个问题最简单最明显的例子就是各种Smalltalk系统,它们把所有程序视为一个完整的系统。程序并不是在另一个系统内运行的程序(即不是像Unix中的进程,而是启动后的系统中的一部分)。

Smalltalk系统提供了“对象”和“消息”的概念,而没有“程序”(或文件)的概念:系统是一组互相发送消息的对象;每个对象都像一个微型系统(负责接收和发送消息),每个微型系统都有自己的行为;一些特殊对象称为类,它们负责大量类似对象的行为定义;输入设备、输出设备和其他用户界面设备都表示成对象;事件和交互表示成消息。

对这个系统进行编程需要通过发送消息来重新配置对象的集合,或者在需要的时候创建一些新对象和类。但它不需要编写程序。

该系统中没有编译,因此它只有一个“阶段”,也就是说系统总是活跃的。系统支持自动持久,因此当系统关闭后再打开时,对象会回到上次的状态。

这个系统中还有许多有趣的地方:对象可能有多种表示方法,所有使用该系统的人都可以用,无论是用户还是程序员。

对象间的消息传递没有内置的验证系统,但是我们可以想象根据某些概念进行分层,比如引入某种一致性检查,来检查对象簇,或在对象间的点对点“连接”建立时的进行检查。

这里并不是说Smalltalk是一个更好的系统,而是它从根本上揭示了一个完全不同的系统观点,而且还可能有其他不同且更有趣的观点。

系统观点

程序只是大系统中的一小部分。通过编写程序的方式来制作系统,意味着首先我们需要将系统分割成程序,这些程序有各自的特定特征。我们也可以用许多其他方法来分割系统——这正是我们应该探索的空间。

我们可以对比一下以程序为中心的观点和与系统为中心的观点,如下所示:

系统分割的大部分在我们开始编写之前就已经完成了,它通过主流软件提供的概念巩固自己的地位:操作系统、文件、应用程序、数据库、编译器等。在我看来,我们需要重新考虑整个系统分解模型。仅仅发明某一既有部分的新版本(例如新的文本编程语言)不会危害到它,因为我们仍然在相同的模型中运行。

我们需要一种不同的方法来分割系统。为了进一步说明我的观点,下面是一些模糊的想法。如果我们设计一个新的操作系统,那么实际上我们就是在重新定义操作系统的意义。

不同轴上的自由度

虽然Smalltalk模型在单个“空间”内保存了大量对象,但我们可以想象有一个系统,里面的每个对象都有内部空间,空间里保存了一组内部对象,依此类推。这样就在设计中引入了递归。

从另一个方向,我们还可以考虑用增量模型替换先写后运行的编程思想(即“提交论文”的模型),在增量模型中程序员可以连续提供更多有关期望行为的细节,以及细化该行为的约束求解系统(即“对话”模型)。

另一种方法是引入时间管理,将其作为基板的第一个类概念,这样可以给所有工作成果加上版本进行管理,并追踪每个版本的变迁。这意味着你可以在任何上下文中回复或前进,例如暂停或回滚多个跨度。

如果在操作系统里创建一个高级的消息模型,怎么样呢?那我们就不需要重实现各个类型的字节显示方式了。

或许我们可以运行一个虚拟机,并在这个虚拟机上编程,那么分配、隔离和分割在多台机器上的执行任务就会更加容易。

我们的系统是否可以成为一个巨大的互连单元网格,拥有Excel的功能、一些合理的命名空间以及自动处理更新?输入/输出也可以表示为特殊的单元格。

我们认为在设计新的编程语言时我们有很多自由,但实际上整个主流编程语言只是主流系统的新兴模式。不同的基板会产生不同的模式。

如果系统给我们一些响应单元,而不是'文件'和'进程',那么'编程语言'会是什么样子?有关语法的争论将会大大不同,因为我们需要处理的是单元而不是自由形式的纯文本。反应度是系统核心功能的一部分,因此我们根本无需想象和设计构建系统。

语言和工具之间的界限开始变得模糊。

这个领域中有太多的选择可供探索,甚至是我们引入概念的顺序也会产生影响。也许我们可以在这个系统中寻找我们了解的好点子,看看是否可以提炼出本质?接下来该怎么办我也不是很清楚,但这让我感到兴奋。

相关的工作

在这篇优秀的论文Semprola paper(https://www.shift-society.org/salon/papers/2018/revised/semprola.pdf)中,Oli Sharpe写道:

另一种传统的选择是,将程序视为一个孤立的数学或其他形式的构造,其语义主要在编译时参考自身及其导入的库来确定。考虑到编程的历史,我们继承这一观点是很合理的,但是如今许多“程序”实际上只是一个更大的、“活跃的”程序和服务网络中的一小部分,每个程序和服务都按照自己的频率更新。因此,没有统一的编译时间,而某一部分与整体相关的语义即使没有更新,也可以跟着整体一起更新。

这段描写很好地捕捉了我们在以程序为中心的思维模式中采用的观点。另一篇很棒的文章是Tomas Petricek写的交互式编程(http://tomasp.net/blog/2018/programming-interaction/),其中写道:

换句话说,编程语言研究不应该学习程序,而应该学习编程!

Tomas强调了要查看整个工作流程,而不是只关注“输入程序”的最终产品。

总结

我们不应该考虑“编写程序”,而是应该将“制作系统”作为首要目标。这个系统是一个不断发展且永远存在的实体,我们希望使用抽象的概念(我们称之为“软件基板”)来编写这个系统。那么我们的核心基板都有哪些想法、概念和抽象呢?这正是我们需要提出的问题。

在初学者的心目中有很多种可能性,但在专家的脑海里却几乎没有。——Shunryu Suzuki

我们需要站在初学者的立场重新思考编程。

原文:https://shalabh.com/programmable-systems/systems-not-programs.html

作者:shalabh,美国软件工程师,主要从事Python开发。

译者:弯月,责编:郭芮

推荐阅读:

  • 用 Python 分析了 10000 场吃鸡数据,原来吃鸡要这么玩!

  • 马克·扎克伯格帝国的衰落

  • Java 11 中 11 个不为人知的瑰宝

  • 老码农冒死揭开行业黑幕:如何编写无法维护的代码

  • 2018最后一战:25天编程PK赛!

  • 想让马云成为你的老大?揭秘阿里面试情景

  • 通证简史|从日进斗金到夹缝求存, 细数Token的前世今生

  • 如何用 Python 实现选择排序?

开发者编程时应该围着“程序”转吗?相关推荐

  1. 学习编程时真正值得一读的一篇文章 与 书籍

    Teach Yourself Programming in Ten Years 彼得·诺维格(Peter Norvig)是美国计算机科学家.他是Google,LLC的研究总监,并曾担任Google搜索 ...

  2. c语言程序框一点数字就消失,你用C语言编程时,会犯下面的错误吗?

    原标题:你用C语言编程时,会犯下面的错误吗? C编译的程序对语法检查并不像其它高级语言那么严格,这就给编程人员留下"灵活的余地",但还是由于这个灵活给程序的调试带来了许多不便,尤其 ...

  3. 编程程序的名称要记住吗_学习编程时要记住的5件事

    编程程序的名称要记住吗 by Kurt 由库尔特 学习编程时要记住的5件事 (5 Things to Remember When You're Learning to Program) Learnin ...

  4. 编程时程序无错却崩溃_人间真实:程序员的 60 个崩溃瞬间!

    源 / 程序员最幽默(ID:humor1024) @程序员,你是否曾经历过这些令你分分钟崩溃或啼笑皆非的绝望瞬间?前方高能预警,这不是演习! 1. 公司实习生找 Bug 2. 在调试时,将断点设置在错 ...

  5. 编程时程序无错却崩溃_程序员极度崩溃的 60 个瞬间,看到哪一个你哭了?

    传智点击蓝字关注我们↑↑↑↑ 时光如流,岁月不居,不知不觉中,我们迎来了充满希望的2019年.回首过去,收获与遗憾并存,总免不了有太多的感动,特别是整日加班工作的程序员们,相信他们的工作中一定有很多不 ...

  6. 程序员如何提高编程时打字速度的5个Tips

    文章目录 程序员如何提高编程时打字速度 前言 打字速度等级 测试编程时打字速度 提高编程时打字速度的5个Tips Tips1: 选用合适的键盘 Tips2: 保持正确的坐姿和打字姿势 Tips3: 选 ...

  7. 如果当初学习编程时能有人给我这些忠告该多好

    Cecily Carver  是多伦多的一位程序媛,和 Jennie Faber 一起创办了一个游戏制作工作室.她喜欢歌剧.舞蹈和弹钢琴.Cecily 在这篇文章分享她在编程道路上的所感所想,给出很多 ...

  8. windows游戏编程_2020年适合程序员编程的笔记本电脑推荐

    在购买编程笔记本电脑时,一套智能的基准规格包括至少 8GB 的内存.像样的 SSD.强大的集成 GPU 和一个 i5 或 i7 处理器.虽然这些基准配置很好,但它们不足以帮助您找到最好的笔记本电脑.在 ...

  9. 英文 程序员编程技能描述_程序员最重要的非编程技能

    英文 程序员编程技能描述 by Ali Spittel 通过Ali Spittel 程序员最重要的非编程技能 (The most important non-programming skills fo ...

最新文章

  1. 输出9*9口诀python-Python输出9*9乘法表的方法
  2. oracle触发器的测试,ORACLE触发器的测试
  3. CentOS6.7 时间同步
  4. 内部类、包、修饰符、代码块
  5. 怎么把python程序发给别人_想把你写的Python程序发给别人用?打包成exe啊!
  6. JMS学习一(JMS介绍)
  7. [刷题]算法竞赛入门经典(第2版) 5-2/UVa1594 - Ducci Sequence
  8. 云服务器重启后网站打不开及FTP连不上的原因及解决方法
  9. 亚马逊向GuardDuty服务添加三种新的威胁检测规则
  10. timimg学习数据删了_如何评价Timing这个督促人学习的软件?
  11. 【转】在唯一密钥属性“value”设置为“***”时,无法添加类型为“add”的重复集合项解决方法
  12. asp.net+mysql,asp.net+mysql后台盲注入
  13. 如何在计算机上增加一个磁盘分区,电脑怎么添加硬盘分区
  14. 如何使用电脑将png转ico格式?赶快跟着小编学起来
  15. 学习记录 Halcon 图片拼接
  16. 2020-03-02
  17. pgm图像修改java_PGM图片格式与代码
  18. \t\t林荫苗圃 苗木和苗圃 好苗木种植技术是关键 它好我也好
  19. Html之 图像标记
  20. 快速准确读取发票信息——发票扫描识别系统

热门文章

  1. 怎么爬before after之间的内容_关于伪元素::before和::after的用法
  2. 安装mysql时出现的缺少msvcr120.dll和msvcp120.dll问题的解决方案
  3. WebDriver使用入门
  4. 碳酸铜行业调研报告 - 市场现状分析与发展前景预测
  5. 中国冷链行业市场供需与战略研究报告
  6. linux系统查看已连接串口,Linux下串口连接的简单测试
  7. requesbodys.java_这个requestBody的正确swagger-annotation是什么?
  8. Java static、 final修饰符
  9. Linus:“免费”不是最重要的,“源代码公开”才是,Linux 30岁生日快乐!
  10. 谷歌:开源捐赠需分成,否则下架!