成功程序员的基础实用编程技巧






4.90/5 (34投票s)
所有程序员的实用主义清单
引言
编写优秀、成功的软件非常困难——极其困难。
因此,对于每个程序员来说,了解、理解和应用软件开发的基本原则至关重要——这些是经过实践检验的实用建议和规则,可以帮助我们在最短的时间内创建出最佳的软件。
在本文中,我试图整理出一套我认为最相关的基本原则。如果您是经验丰富的程序员,那么您可能对其中大部分/全部都很熟悉。如果您错过了任何建议,请通过发表评论与我们分享。
请注意
- 本文中的原则主要涉及设计和编写代码。软件开发项目要成功,还有其他重要方面(例如良好的用户界面、人际交往等),但它们超出了本文档的范围。
- 以下原则仅涵盖基本原则,旨在普遍适用。不包含针对特定编程环境(编程语言、库、工具和架构)的建议。
这些技巧分为三类
- 通用指南
- 数据设计
- 编写代码(将在本文的第二部分发布)
让我们开始吧。
通用指南
一切都应该尽可能简单,但不能更简单! - 阿尔伯特·爱因斯坦
简单的工具和概念可以快速理解,易于使用,不易出错,并能提高我们的生产力。
我们都喜欢简单。简单使工作和生活更令人愉快。
然而,我们必须警惕过度简化,正如爱因斯坦这句优美的名言结尾所指出的那样。
因此:保持简单,但不要过于简单!
许多名人提倡简洁。以下是一些例子
引用简洁是可靠性的先决条件。
简洁明了……决定成功与失败。
荷兰计算机科学家;《goto 语句被认为是有害的》一文的作者
引用控制复杂性是计算机编程的精髓。
计算机科学家和作家;Unix 的联合开发者
引用简洁是极致的优雅。
引用简洁将普通变为非凡。
《呆伯特》的创作者
引用如果你不能简单地解释清楚,说明你理解得还不够深入。
物理学家;天才
引用真理总是存在于简单之中,而不是事物的多样性和混乱之中。
数学家;天文学家;神学家;作家和物理学家
如果注定要失败,那么尽快失败!
大多数软件项目都会失败。这是一个令人 sad 且不容否认的事实。
如果一个项目被判定会失败,那么它应该尽快失败,以限制损失,并将时间和资源释放给其他(有望)不会失败的项目。
在这种情况下,快速失败意味着问题应该尽早被发现和处理。我们越晚解决问题,浪费的时间、精力和资源就越多。累积损失随时间呈指数级增长。
例如,在设计阶段纠正一个设计缺陷既简单又便宜。但一旦软件投入生产并被许多人使用,修复错误通常非常昂贵且令人沮丧。
引用我们越早“失败”并越快学习,成功的机会就越大。早失败可以为您节省时间和金钱。
Adobe 产品经理
引用快速测试,快速失败,快速调整。
畅销书《追求卓越》的作者
追求“够好”,而非“完美”。然后发布!
创建完美的软件(无 bug,功能齐全,用户界面最优,文档优秀等)耗时且昂贵,除非我们处理的是一个非常小的项目。在大多数情况下,由于实际限制,实现完美是不可能的。
即使是软件行业的大公司,拥有顶尖的开发人员和巨大的预算,也写不出完美的软件。这就是为什么他们不断提供补丁和新版本。
因此,请按以下方式进行
- 设定目标和优先级
- 创建原型
- 交付“足够好”的软件
- 持续改进(参见下一项)
![]() | ![]() | ![]() |
原型 | 足够好 | 更好 |
引用你无法编写 100% 完美的代码。即使你做到了,6 个月后它也不会完美。
CodeProject 联合创始人
引用在短暂的计算历史中,没有人编写过完美的软件。
作家;《程序员的修炼之道》合著者
引用现在交付 90% 的功能比永远不交付 100% 的功能要好。
计算机科学家和作家;Unix 的联合开发者
引用寻找完美的解决方案常常会导致停滞和沮丧。坚持不懈,容忍不完美,追求进步,并致力于做到最好,这些都是健康的,最有可能带来最佳结果。
心理治疗师
倾听用户的声音!
实践表明:
- 软件开发者无法预测用户真正想要的一切。
- 用户通常不知道确切想要什么,除非他们使用软件一段时间。
- 用户的满意度是软件成功的决定性因素。
我们希望用户满意。因此,最佳方法是迭代式方法,如下所示

引用在花费大量时间尝试了一些营销技巧后,[乔尔·斯波尔斯基,Stack Exchange 联合创始人] 得出结论(5 年后):没有什么比改进你的产品更有效。制造人们想要的出色软件并不断改进它。与你的客户(用户)交谈并倾听。找出他们的需求。
引用... 我们为每个主要产品功能构建原型。我们很早就与预发布用户和关键客户进行测试,并且肯定在实现之前就进行测试。是的,我们确实经常“失败”,这很棒!很棒,因为我们在过程中学到了很多东西,并最大程度地降低了长期失败的风险。最终,我们以创新的方式,富有同情心地解决了客户的真实需求。
Adobe 产品经理
引用
引用一个程序最重要的属性是它是否实现了用户的意图。
计算机科学家;1980 年 ACM 图灵奖得主
数据设计
在编写代码之前,仔细设计您的数据!
每当你创建一个应用程序时,都要从仔细设计数据结构及其关系开始。在编写代码之前这样做。
精心设计的数据结构可以带来更简单、更易于维护的代码,更少的 bug,更好的性能和更少的内存消耗。
区别可能很显著。
引用一项又一项研究表明,最优秀的设计师产生[数据]结构的速度更快、体积更小、更简单、更清晰,并且付出的努力更少。伟大与平庸的方法之间的差异接近一个数量级。
书籍《银弹》
引用给我看你的流程图(代码),隐瞒你的表格(数据结构),我将继续感到困惑。给我看你的表格(数据结构),我通常不需要你的流程图(代码);它们会很明显。
书籍《人月神话》
引用表征规则:将知识折叠成数据,这样程序逻辑就可以是愚蠢而健壮的。
数据主导一切。如果你选择了正确的数据结构并组织得当,算法几乎总是显而易见的。数据结构,而不是算法,是编程的核心。
引用我坚信围绕数据设计你的代码,而不是反之。
糟糕的程序员担心代码。好的程序员担心数据结构及其关系。
Linux 的创造者
引用如果你能正确地处理数据结构及其不变量,大部分代码都会自己写出来。
书籍《程序员访谈录

除非有充分的理由,否则使所有数据结构都不可变!
不可变数据结构更易于理解、使用且不易出错,因为
- 创建后,状态不再改变。没有状态转换,没有临时无效状态,也没有必要进行同步、锁定或防御性复制。
- 不可变数据可以在并发/并行计算环境中自由共享——没有损坏数据、死锁或其他难以解决和修复的棘手问题的风险。
- 基于不可变数据计算出的结果可以轻松缓存以获得更好的性能。
但是,不可变数据结构并不总是最佳选择。例如,每次更改都克隆整个结构可能会非常昂贵(时间和空间)。在某些情况下(例如游戏或 GUI 应用程序),可变数据结构更适合。
此外,如果两个对象需要直接相互引用,那么这些对象必须是可变的。例如,树中的父节点和子节点直接相互引用,互为朋友(A 指向 B,B 指向 A)等。如果在这种情况下必须保持不可变性,那么一个可能的解决方案是有一个额外的数据结构来描述关系,例如一组表示一对相互关联对象的元组。
将允许的值集限制为最小可能的值!
限制数据类型允许值的集合
-
有助于理解数据类型
-
消除了因值错误而导致的误行为或严重故障的风险
-
简化了处理数据的代码
例如,考虑数据类型 `employee` 的 `name` 字段。允许在 `name` 中存储任何字符串,可能会发生以下情况
-
长字符串可能导致缓冲区溢出(取决于编程语言)、内存耗尽或其他软件故障。
-
名称中无效的字符,但在 JavaScript 和 SQL 中被用作有效符号(例如 `<`、`>` 和 `"`)可能为 SQL 注入和/或脚本注入等攻击打开大门。
-
如果代码没有正确处理这些值,空字符串或 `null` 字符串可能导致 bug。
为避免这些风险,应限制 `name` 字段。例如,以下简单的正则表达式消除了上述所有问题
[a-zA-Z ]{1,70}
此正则表达式将名称限制为最多 70 个字符,要求至少一个字符,并且只允许字母和空格。请注意,上述正则表达式过于简化,不适用于必须允许包含连字符、撇号等的名称的实际应用程序。有关更多信息,请参阅下面的评论,其中包含 Chad3F 的信息。
保护数据免受无效值的影响(尤其是在从外部源读取数据时)通常被认为是编写安全软件最重要的规则。(例如,请参阅OWASP Top 10 关键 Web 应用程序漏洞和Top 10 安全编码实践)
SQL 注入的示例,在一个数据录入表单中
JavaScript 注入尝试的示例
大多数情况下,默认值应该是允许值集中最严格的。
通过选择最严格的值作为默认值,我们始终是安全的。
更宽松的值应明确声明(在代码、配置文件等中)。
例如
-
写入文件的函数,默认情况下不应覆盖现有文件。
-
默认应启用所有编译器警告。
-
在多用户应用程序中添加新用户时,默认应授予最低的权限。
最后一个例子表明,严格的默认值并不总是最佳选择。它们可能令人烦恼。如果多用户应用程序只由一个人在其 PC 上使用,那么用户显然希望默认拥有完全的权限。因此,最佳默认值有时取决于多种因素。
GUI 中严格默认值的示例

避免数据冗余!
在不同位置存储可变数据的副本既容易出错,又费力且昂贵,因为
-
在数据更改时,存在未更新所有位置的风险——由于健忘、技术问题、安全问题等。这可能导致数据不一致和损坏,并最终导致严重的软件故障。
-
有时需要实现锁定/同步机制并为每次数据修改(创建、更新和删除操作)激活,以避免在数据修改过程中访问无效数据。实现这些机制可能非常棘手且容易出错。
-
需要额外的内存来存储副本。
普通例子:一个推销员错过了重要的约会。原因:他把约会录入了他 PC 上的日程表,但忘记将其数据同步到手机上的另一个日程表。如果两个日程表的数据都存储在一个地方(例如云端),他就不会错过约会了。
考虑使用通用、标准化格式将数据存储在纯文本文件中!
使用文本文件作为存储介质有许多优点
-
所有操作系统都完全支持文本文件。无需安装和配置数据库服务器等附加软件。
-
文本文件易于人类阅读和操作。这对于调试非常方便。
-
它们还可以轻松地被许多第三方应用程序(用任何编程语言编写)和工具读取和操作。例如,Unix 提供了许多有用的文本处理工具,如 grep、awk、sed 等。
-
使用 JSON、XML 和 CSV 等标准格式可以使数据被许多现有应用程序查询、排序、过滤、搜索、打印和转换。例如,CSV 文件可以轻松地在电子表格应用程序中使用。
然而,文本文件也有严重的局限性,尤其是在大数据的情况下。复杂查询(带有过滤器和连接)、更新和删除操作、事务处理、数据加密和其他功能可能需要手动实现,并且可能非常低效。当涉及大数据时,将其存储在数据库中通常是唯一可行的选择。
此外,将数据存储为字符(而不是位)可能会消耗更多的空间和时间。因此,二进制数据有时是不可避免的。
使用文本表示图形的一个很好的例子是 `SVG`(可缩放矢量图形)。
这是一个 SVG 文件的简单示例(SVG_example.svg)
<?xml version="1.0" encoding="UTF-8"?> <svg xmlns="http://www.w3.org/2000/svg" width="140" height="140" > <circle cx="70" cy="70" r="40" stroke="red" stroke-width="4" fill="yellow" /> </svg>
用(例如)您的网络浏览器打开文件会显示以下图像

引用编写程序来处理文本流,因为这是一个通用的接口。
Unix 管道的发明者
引用Unix 传统强烈鼓励编写读取和写入简单、文本化、面向流的、设备无关的格式的程序。
《Unix 编程艺术》
编写代码
请继续阅读第二部分。