如果您编写过代码,您就会知道熟练掌握它需要练习。无论是几个月还是几年,都不可避免地会有顿悟的时刻。
我们想听听那一刻,所以我们邀请社区成员分享他们坐下来编写代码并真正为之自豪的时刻。
我自己的编码经历可以追溯到 70 年代的大学时代。我学习了如何解析算术表达式并将它们放入逆波兰表示法中。然后,我发现,就像乘法是重复加法一样,除法是重复减法。但是,您可以通过从适当的 10 的幂开始来加快速度。因此,我在运行 RSTS 的 16 位 PDP 11/45 上编写了一个 BASIC Plus 程序来进行多精度算术。然后,我添加了一堆用于各种计算的子程序。我通过计算 PI 到 45 位数字来测试它。它运行了半个小时,但成功了。我可能已将其保存到 DECtape。——Greg Scott
在 20 世纪 90 年代中期,我作为一个小型咨询团队(三名程序员)的成员,为一家大型钢铁公司从事生产计划和调度工作。该应用程序将在 Hewlett-Packard 工作站(当时非常流行)上交付,GUI 将使用 XWindows 完成。令我们惊讶的是,CommonLisp 推出了第一个体面的 Motif 接口,Motif 具有(当时)非常好的小部件工具包。结果,整个应用程序都用 CommonLisp 完成,并在工作站上表现良好。用 Lisp 做一些商业项目非常有趣。
正如您可能猜到的那样,该公司随后希望从 Hewlett-Packard 工作站移植到更便宜的东西,因此,大约四年后,我们用 C 重写了该应用程序,性能得到了预期的提升。——Marty Kalin
这个话题唤起了一个古老的记忆。虽然我从编写第一个 C 程序打印三角形到从头开始编写 Kubernetes 的验证准入 webhook 和运算符中获得了许多自我满足的时刻。
长期以来,我看到并玩过用各种语言编写的游戏,因此我有一种不可抗拒的冲动,想用 bash shell 脚本编写一些可能的游戏。
我编写了第一个游戏,井字棋,然后是扫雷,但它们从未发布过,直到几年前,我将它们提交到 GitHub,人们开始喜欢它们。
我很高兴有机会在这个网站上发表文章。——Abhishek Tamrakar
虽然还有其他更新的作品,但两段相当老旧的打油诗浮现在脑海,主要是因为当我能够检查输出并验证我确实理解了我正在使用的罗塞塔石碑,足以破译这些神秘的数据时,出现了“灵光一闪!”的时刻
- UNPAL:用 DECsystem-10 的 MACRO-10 汇编语言编写的交叉反汇编器。它可以接受 PDP-11 二进制文件,并将它们转换回 PDP-11 MACRO-11 汇编语言。非常感谢当时编写文档的人们,特别是 DEC-10 的大约 17 卷文档,其中充满了大量信息和一些幽默。UNPAL 流传到了世界各地,并且可能是我学校或工作场所之外的人们使用的唯一一段代码。(另一方面,我的一些文档/教程在许多外部邮件列表和网站上流传开来。)
- MUNSTER:用一种我尚未学习的语言编写,用于我从未遇到过的操作系统,在一台我只听说过的计算机上,用于我一无所知的合成器,使用神秘的文档。语言是 C,机器是 Atari 1040-ST (? ST-1040?),操作系统——我不记得了,但它与 GEM 有关?合成器是 Korg M1——因此得名“munster”(m1-ster)。同时学习所有组件是一次非常棒的学习体验。该代码将转储和恢复音乐实验室中八个合成器的内存。Korg 手册(恕我直言)未能真正解释数据格式。附录是一个迷宫般曲折的小通道,到处都是“注释 8:请参阅表 5 中的注释 14。表 5,注释 14:请参阅表 2 中的注释 3、4 和 7。”最终,我从一张没有任何真正解释的图片中破译出来,当转储数据时,每组七个 8 位字节被转换为八个 7 位字节,方法是从七个字节中的每一个字节中剥离高位,并将七个高位前缀到一个额外的字节中,该字节位于七个剥离的字节之前。这必须从附录中的一个微小插图中弄清楚(请参阅手册中的附加屏幕截图)

(Kevin Cole, CCC BY-SA 4.0)
对我来说,绝对是 GSequencer 的同步函数 AgsThread::clock()
。
处理并行性
在 GSequencer 的开发过程中,我遇到了许多障碍。当我开始这个项目时,我对多线程代码执行几乎一无所知。我知道pthread_create()、pthread_mutex_lock()
和 pthread_mutex_unlock()
。
但我需要的是更复杂的同步功能。主要有三种选择——条件锁、屏障和信号量。我选择了条件锁,因为它可以从 GLib-2.0 线程 API 中获得。
条件锁通常不会继续程序流程,直到循环内的条件变为 FALSE。因此,在一个线程中,您可以执行以下操作
gboolean start_wait;
gboolean start_done = FALSE;
static GCond cond;
static GMutex mutex;
/* conditional lock */
g_mutex_lock(&mutex);
if(!start_done){
start_wait = TRUE;
while(start_wait &&
!start_done){
g_cond_wait(&cond,
&mutex);
}
}
g_mutex_unlock(&mutex);
在另一个线程中,您可以唤醒条件锁,如果条件评估为 FALSE,则程序流程将为等待线程继续。
/* signal conditional lock */
g_mutex_lock(&mutex);
start_done = TRUE;
if(start_wait){
g_cond_signal(&cond);
}
g_mutex_unlock(&mutex);
Libags 提供了一个构建在 GLib 线程 API 之上的线程包装器。AgsThread
对象通过 AgsThread::clock()
事件同步线程树。它有点像并行陷阱。

(Joel Krahemann, CC BY-SA 4.0)
树中的所有线程都同步到每秒 AgsThread:max-precision
,因为所有线程都应以完全相同的时间并行运行。我说的是基于节拍的并行性,最大精度为 1000 Hz,每个线程在树中同步 1000 次——为您提供强大的语义,以多线程方式计算确定性结果。
由于我们希望独占运行任务,而不会受到竞争线程的任何干扰,因此在同步后立即涉及互斥锁,然后调用 ags_task_launcher_sync_run()
。请注意,条件锁可以评估为对许多线程都为真。
流重复的节拍数取决于采样率和缓冲区大小。如果您有一个最大精度为 1000 的 AgsThread
,音频 CD 常用的采样率为 44100,缓冲区大小为 512 帧,那么延迟直到重复的计算如下
tic_delay = 1000.0 / 44100.0 * 512.0; // 11.609977324263039
由于您可能需要三个节拍来进行预同步/后同步工作,因此您有八个未使用的节拍。
预同步用于从声卡或 MIDI 设备读取数据。中间节拍执行实际的音频处理。后同步用于输出到声卡或导出到音频文件。
为了使它正常工作,我经历了高峰和低谷。这尤其因为您无法听到或看到线程。GDB 的批处理调试帮助很大。通过批处理调试,您可以检索正在运行的进程的堆栈跟踪。——Joël Kräheman
我不认为我编写过任何特别值得骄傲的代码——我作为一个神经多样性的程序员可能意味着我的情况是,我只是一个具有特定优势和劣势的普通程序员。
但是,多年前,我确实用 C 语言编写了一些代码,并在并行虚拟机中编写了基本示例,当我让它们工作时,我非常高兴。
十多年前,我开设了一个编程课程,向成年学生教授 Java,我很高兴我能够组织起这门课程。
最近我很高兴我设法帮助残疾大学生进行代码错误测试,作为一份兼职工作。——Rikard Grossman-Nielsen
和其他人一样,这让我想起了很久以前的事。我真的不认为自己是开发人员,但我一路走来做了一些开发工作。对我来说,最突出的是顿悟因素,或者正如您所说的“顿悟时刻”。
当我在 UNCW 读书时,我在 OIT 网络组工作,负责管理宿舍的网络。学生们都使用引导程序协议 (BOOTP)(DHCP 的前身)接收他们的 IP 地址注册——配置文件最初是在我们只有大约 30 名学生时手动维护的。那是校园首次向学生提供互联网的第一年!第二年,随着更多宿舍接通线路,人数迅速增长到 200 多人。我编写了一个小型 C 程序来维护配置文件。顿悟和“非常酷的部分”是我的代码可以接触和操作“真实”的东西,而不是代码本身。在这种情况下,是系统上的一个文件。后来在 Java 课上,当我学习如何读取和写入 SQL 服务器时,我也有类似的感觉。
无论如何,从程序中看到真实结果是很酷的。更令人惊奇的是,最初的二进制文件是在 Red Hat 5.1 Linux 系统上编译的,现在仍然可以在我当前的 Fedora 34 Linux 桌面系统上运行!!——Alan Formy-Duval
在 18 岁时,当我为一个小型公司编写一个 Virtual Basic 应用程序来批量自动打印 AutoCAD 文件时,我当然感到自豪。当时,这是我编写的第一个“复杂”应用程序。需要许多用户交互来配置打印机设置。此外,该应用程序使用 Com ActiveX 与 AutoCAD 集成。这很有挑战性。该公司一直使用它直到最近。该应用程序由于与 Windows 10 的不兼容问题而停止工作。他们使用了 18 年,没有出现问题!
我被要求使用今天的技术重写该应用程序。我已经用 Python 编写了新版本。回顾我编写的代码很有趣。它太笨拙了。
附件是第一个版本的屏幕截图。

(Patrik Dufresne, CC BY-SA 4.0)
我曾经将 GitHub 与 Open Humans 平台集成,这在 2019 年是我的 Outreachy 项目的一部分。那是我涉足 Django 的开始,在此过程中我学到了很多关于 API 和速率限制的知识。
此外,最近,我开始使用 Quarkus 并开始使用它构建 REST、GraphQl API。我发现它真的很酷。——Manaswini Das
大约在 1998 年,我感到无聊,决定编写一个游戏。受到 20 世纪 80 年代一款老式 Mac 游戏的启发,我决定创建一个“模拟”游戏,用户可以在其中构建一个简单的“程序”来控制虚拟机器人,然后探索迷宫。环境中散布着奖品和能量丸来为你的机器人供电——但也包含敌人,如果你的机器人撞到它们,它们会损坏你的机器人。我添加了一个能量“成本”,以便每次你的机器人移动或采取任何行动时,它都会消耗掉一点存储的能量。因此,你必须在“捡起奖品”和“寻找能量丸”之间取得平衡。目标是在能量耗尽之前捡起尽可能多的奖品。
我尝试使用 GNU Guile(一种 Scheme 扩展语言)作为编程“后端”,效果很好,即使我真的不懂 Scheme。我弄清楚了足够的 Scheme 来编写一些有趣的机器人程序。
这就是我编写 GNU Robots 的方式。这只是一个为了自娱自乐而做的快速项目,开发和玩起来都很有趣。后来,其他开发人员接手并继续开发,对我的简单代码进行了重大改进。几年前重新发现你仍然可以编译 GNU Robots 并玩玩它们真是太酷了。祝贺新的维护者让它继续运行。——Jim Hall
评论已关闭。