优秀的程序员思考数据结构
原文地址:https://read.engineerscodex.com/p/good-programmers-worry-about-data
我最近在这篇很棒的 Stack Overflow 文章中看到了 Linus Torvalds(Linux 和 Git 的创建者)的一句话。(这篇文章回顾了那篇文章中的许多引述。
它简洁地描述了我最近一直在研究的一个问题:
“糟糕的程序员担心代码。优秀的程序员思考数据结构及其关系。
就在上述引述之前,Linus 说:
Git 基于稳定且文档齐全的数据结构,其本身的设计实际上非常简单。
事实上,我非常支持围绕数据设计代码,而不是相反,我认为这是 git 相当成功的原因之一
…
事实上,我会声称,一个坏程序员和一个好程序员之间的区别在于他认为代码更重要,还是数据结构更重要。
良好的数据结构使代码更易于设计和维护。
它使软件更可靠,系统更易于理解,代码更具可读性。
在设计任何软件时,应用程序逻辑通常遵循数据模型的设计。
将数据模型视为事后的想法会导致更多的工作。
反之亦然 —— 拥有经过深思熟虑的数据模型可以更轻松地在复杂系统上进行迁移和构建。
当我读到这句话时,我实际上能回忆起过去无数的例子。
我曾经参与过一个项目,我们花了相当长的时间优化复杂的算法,结果才意识到,通过重组我们的数据,我们可以消除所有的问题。
我们将 500 行代码的函数替换为 50 行代码和精心设计的数据结构。
新代码不仅速度更快,而且更容易理解和维护。(当然,问题也转移到了“堆栈下游”,即大部分工作都变成了重组已有的数据)
另一个相关的引述是在 “The Art of Unix Programming” 中:
表示法则(Rule of Representation):将知识融入数据中,这样程序逻辑就可以既 “愚蠢” 又健壮。
即使是最简单的过程逻辑,人类也很难验证其正确性,但及其复杂的数据结构相当容易建模和追根溯源。
要了解这一点,请将 50 个节点的树的图表与 50 行程序的流程图的表达力和解释力进行比较。
或者,将表示转换表的数组初始值设定项与等效的 switch 语句进行比较。其理解表达力和清晰度的差异是巨大的。
/* 将数字转换为英文单词 */// 使用数据结构建模复杂度
const char* number_to_word(int num) {const char* words[] = {"one", "two", "three", "four", "five"};if(num >= 1 && num <= 5) {return words[num - 1]; // 减1是因为数组索引从0开始} else {return "invalid number"; // 超出范围的数字}
}// 使用代码逻辑建模复杂度,当值相当多时(例如 100 个),这种写法将变得相当复杂
// 这种写法经常还会诱导我们在特定的 case 条件中加入特定的处理逻辑,整个代码变得难以和维护
const char* number_to_word_switch(int num) {switch(num) {case 1: return "one";case 2: return "two";case 3: return "three";case 4: return "four";case 5: return "five";default: return "invalid number"; // 超出范围的数字}
}
数据比程序逻辑更容易处理。
因此,当您看到数据结构复杂性和代码复杂性之间的选择时,请选择前者。
更进一步:在改进设计时,您应该积极寻求将复杂性从代码转移到数据。
这个观点并不是Unix社区首创的,但许多Unix代码都受到了它的影响。特别是C语言在处理指针上的强大能力,促使开发者从内核层面起,到更高编码层级,都采用了可以动态修改的引用结构。在这些结构中,简单的指针追踪常常承担起了在其他语言中需要通过更复杂的程序代码来实现的工作。
这里的实用建议是从数据入手。尽量通过对你的接口或数据库使用更严格的类型定义来减少代码的复杂性。额外花一些时间提前深入思考数据结构的设计。
这并不是说代码不重要。显然,一切都很重要 —— 但在深入研究与代码相关的细节之前,有一个强大的高级方法来了解数据的流动方式以及不同组件如何交互是非常有帮助的。
一些 “接口或数据库使用更严格的类型定义” 的例子
使用枚举代替魔法字符串:
通过枚举确保只有预定义的值被接受,这样可以避免无效值的出现,并在编译时就捕捉到错误。
public enum Status {OPEN, IN_PROGRESS, CLOSED;}public void updateStatus(Status newStatus) {// 只接受Status枚举的值}
采用明确的数据结构而非泛型容器
使用明确的类或结构体来代替如 Map 或 Dictionary 等通用容器,可以提供更强的类型检查。
public class User {private String name;private int age;// 使用构造函数和明确的字段类型public User(String name, int age) {this.name = name;this.age = age;}// 相应的getter和setter方法...}// 应该使用具体的类型public User getUserInfo(...)...// 而不是使用容器public Map<String, Object> getUserInfo(...)...
在数据库中使用严格的模式:
定义数据库模式时,使用严格的字段类型和约束条件,如非空、唯一性约束或外键约束。
CREATE TABLE users (id INT PRIMARY KEY,name VARCHAR(100) NOT NULL,age INT NOT NULL CHECK (age > 0));
利用类型系统进行验证:
在编程中利用类型系统来强制数据的结构和预期的使用方式。
例如在弱类型语言 python 中使用 type hint 机制
使用类型转换和校验库:
使用类型转换和校验库如Joi或Yup等,来确保数据在运行时满足预定义的模式。
const schema = Joi.object({name: Joi.string().required(),age: Joi.number().integer().min(0).required(),});// 使用schema来验证数据const { error, value } = schema.validate({ name: 'Alice', age: 25 });if (error) {throw new Error(error.details[0].message);}
相关文章:
优秀的程序员思考数据结构
原文地址:https://read.engineerscodex.com/p/good-programmers-worry-about-data 我最近在这篇很棒的 Stack Overflow 文章中看到了 Linus Torvalds(Linux 和 Git 的创建者)的一句话。(这篇文章回顾了那篇文章中的许多引述。 它…...
「C/C++」C/C++标准库之#include<cstdlib>通用工具库
✨博客主页何曾参静谧的博客📌文章专栏「C/C」C/C程序设计📚全部专栏「VS」Visual Studio「C/C」C/C程序设计「UG/NX」BlockUI集合「Win」Windows程序设计「DSA」数据结构与算法「UG/NX」NX二次开发「QT」QT5程序设计「File」数据文件格式「PK」Parasoli…...
Oracle视频基础1.1.3练习
1.1.3 需求: 完整格式查看所有用户进程里的oracle后台进程 查看物理网卡,虚拟网卡的ip地址 ps -ef | grep oracle /sbin/ifconfig要以完整格式查看所有用户进程中的 Oracle 后台进程,并查看物理和虚拟网卡的 IP 地址,可以使用以下…...
python项目实战——多协程下载美女图片
协程 文章目录 协程协程的优劣势什么是IO密集型任务特点示例与 CPU 密集型任务的对比处理 I/O 密集型任务的方式总结 创建并使用协程asyncio模块 创建协程函数运行协程函数asyncio.run(main())aiohttp模块调用aiohttp模块步骤 aiofiles————协程异步函数遇到的问题一 await …...
基于.NET 8.0,C#中Microsoft.Office.Interop.Excel来操作office365的excel
开发环境: Visual Studio 2022 office365 项目模板:WPF应用程序 框架:.NET 8.0 依赖:Microsoft.Office.Interop.Excel 注意: 1.使用Microsoft.Office.Interop.Excel库时,服务器或电脑里面必须安装得…...
使用无线方式连接Android设备进行调试的两种方法
1.使用配对码配对设备方式 手机(或者平板等安卓设备)和电脑需连接在同一WiFi 下;保证 SDK 为最新版本(adb --version ≥ 30.0.0); step1.手机启用开发者选项和无线调试模式(会提示确认ÿ…...
Valgrind的使用
Valgrind 是一个强大的开源工具,用于检测程序中的内存错误、内存泄漏以及线程问题。它广泛应用于 C/C++ 等需要手动管理内存的编程语言中。以下内容将详细介绍 Valgrind 的安装、基本使用方法、常用命令及其输出结果的解析。 1. 什么是 Valgrind? Valgrind 是一个用于内存调…...
微信小程序瀑布流实现,瀑布流长度不均等解决方法
这是一开始实现的瀑布流,将数据分为奇数列和偶数列 <view class"content-left"><block wx:for"{{list}}" wx:key"list"><template isitem-data data{{...item}} wx:if"{{index % 2 0}}"></template&…...
Notepad++通过自定义语言实现日志按照不同级别高亮
借助Notepad的自定义语言可以实现日志的按照不同级别的高亮; 参考: https://blog.csdn.net/commshare/article/details/131208656 在此基础上做了一点修改效果如下: xml文件: <NotepadPlus><UserLang name"Ansibl…...
2024年四川省大学生程序设计竞赛 补题记录
文章目录 Problem A. 逆序对染色(思维树状数组)Problem B. 连接召唤(贪心)Problem E. L 型覆盖检查器(模拟)Problem F. 小球进洞:平面版(几何)Problem G. 函数查询Proble…...
17_事件的处理
目录 绑定事件与解绑事件优化事件的绑定和解绑方式处理不同事件类型的绑定处理同一事件类型多个事件处理函数事件冒泡与更新时机问题 绑定事件与解绑事件 既然要处理事件,那么首先面临的问题是如何在 vnode 中描述这个事件,在 vnode.props 中࿰…...
1FreeRTOS学习(队列、二值信号量、计数型信号量之间的相同点和不同点)
相同点: (1)传递区间 队列、二值信号量、计数型信号量均可用在任务与任务,任务与中断之间进行消息传递 (2) 传递方式 创建队列--发送队列--接受队列 创建二值信号量--发送二值信号量--接受二值信号量 创建计…...
数据库设计与范式及其应用
数据库设计是数据库管理系统(DBMS)中的核心环节,良好的数据库设计不仅可以提高数据存取的效率,还能增强数据的可维护性和一致性。范式(Normalization)是一种设计原则,用于减少数据冗余和提高数据…...
笔记-配置PyTorch(CUDA 12.2)
文章目录 前言一、安装 PyTorch(CUDA 12.2)1. 创建并激活 Conda 环境2. 安装 PyTorch(CUDA 12.2)3. 安装 torch_geometric 及依赖项4. 验证安装 总结 前言 一、安装 PyTorch(CUDA 12.2) 1. 创建并激活 Con…...
[C++]——红黑树(附源码)
目录 一、前言 二、正文 2.1 红黑树的概念 2.2 红黑树的性质 2.3红黑树节点的定义 2.4 红黑树的插入 2.4.1 情况一 2.4.2 情况二 编辑 2.4.3 情况三 2.5 红黑树的验证 三、全部代码 四、结语 一、前言 在上一篇博客中,为小伙伴们进行了AVL树的讲解&#…...
网络文件系统搭建
在CentOS7上搭建网络文件系统(NFS),并让客户端进行挂载,具体步骤如下: 1. 服务器端操作 安装NFS服务器软件包: 执行以下命令安装NFS服务: sudo yum install nfs-utils -y 启动并启用NFS服务&…...
基于vue、VantUI、django的程序设计
首先构建vue项目,构建项目点这里 安装 npm install axios axios简介 Axios 是一个基于 promise 的 HTTP 库,用于发起请求和接收响应,实现异步操作 基本使用 axios对象 请求响应拦截 在utils文件夹里新建ajax.js 创建一个axios对象并…...
京准电钟解读:NTP网络对时服务器助力厂区改造方案
京准电钟解读:NTP网络对时服务器助力厂区改造方案 京准电钟解读:NTP网络对时服务器助力厂区改造方案 1)系统概述 时钟系统可通过网络进行管理及时间校对,为厂区提供高精度、全天时、全天候 的授时服务,统一全厂各种系统…...
本地docker-compose仓库搭建以及推送docker镜像到仓库
前言 以下部分知识只适用于linux,不适合小白,请自行甄别执行 1.搭建 #参考 https://blog.csdn.net/u011535199/article/details/107457275 version: 3 services:registry:restart: alwaysimage: registry:2ports:- 5000:5000environment:#REGISTRY_HT…...
WPF+MVVM案例实战(八)- 自定义开关控件封装实现
文章目录 1、案例运行效果2、项目准备2、功能实现1、控件模板实现2、控件封装1、目录与文件创建2、各文件功能实现 3、开关界面与主窗体菜单实现1、开关界面实现2、主窗体菜单实现 4、源代码获取 1、案例运行效果 2、项目准备 打开项目 Wpf_Examples,新建ToggleBut…...
通信行业硅转向:从专用ASIC到软件定义网络的架构演进
1. 项目概述:通信行业的硅转向 如果你在2016年前后关注过通信设备行业,尤其是那些做核心路由器、骨干网交换机的“大厂”,你大概能感受到一种山雨欲来的氛围。当时,一篇来自EE Times的报道,标题是“Silicon Shift Ahea…...
ABAP选择屏幕进阶:基于用户交互的动态字段控制
1. 动态选择屏幕的核心价值 在ABAP开发中,选择屏幕(Selection Screen)是与用户交互的重要界面。传统的静态选择屏幕往往无法满足复杂业务场景的需求,比如当用户选择不同查询维度时,需要展示完全不同的筛选条件。这时候…...
还在手动整理ai会议纪要浪费宝贵下班时间?2026年这4款真香AI工具3分钟搞定3小时会议
作为挖了快三年AI效率工具的爱好者,我上周刚被3小时项目复盘会的纪要搞到加班到九点,试了一圈新出的工具,直接给大家上结论:听脑AI是目前同类会议纪要工具里最值得用的,没有之一。 直达链接:https://iting…...
AI账号自动化管理工具集:从注册到运维的全流程实战指南
1. 项目概述:一个AI账号自动化管理的“军火库”如果你正在批量使用ChatGPT、Claude、Gemini这些AI服务,或者在做一些相关的开发和研究,那你肯定遇到过这些让人头疼的问题:注册账号需要接码、管理几十上百个API密钥手忙脚乱、临时邮…...
Windows Defender 彻底移除工具:专业级系统安全组件管理解决方案
Windows Defender 彻底移除工具:专业级系统安全组件管理解决方案 【免费下载链接】windows-defender-remover A tool which is uses to remove Windows Defender in Windows 8.x, Windows 10 (every version) and Windows 11. 项目地址: https://gitcode.com/gh_m…...
FGO自动化终极指南:告别枯燥刷本,每天节省3小时游戏时间
FGO自动化终极指南:告别枯燥刷本,每天节省3小时游戏时间 【免费下载链接】FGA Auto-battle app for F/GO Android 项目地址: https://gitcode.com/gh_mirrors/fg/FGA 你是否厌倦了在《Fate/Grand Order》(FGO)中重复点击刷…...
VideoDownloadHelper深度解析:破解主流视频平台下载限制的技术实战
VideoDownloadHelper深度解析:破解主流视频平台下载限制的技术实战 【免费下载链接】VideoDownloadHelper Chrome Extension to Help Download Video for Some Video Sites. 项目地址: https://gitcode.com/gh_mirrors/vi/VideoDownloadHelper 还在为无法保存…...
终极分屏神器Nucleus Co-Op:一台电脑实现4人同时开黑完整指南
终极分屏神器Nucleus Co-Op:一台电脑实现4人同时开黑完整指南 【免费下载链接】nucleuscoop Starts multiple instances of a game for split-screen multiplayer gaming! 项目地址: https://gitcode.com/gh_mirrors/nu/nucleuscoop 你是否曾因朋友聚会时电脑…...
开发者技能日志工具:用CLI与SQLite构建个人技术成长追踪系统
1. 项目概述:一个技能日志记录器的诞生 最近在整理自己的技术栈和项目经验时,我遇到了一个很多开发者都有的痛点:学了那么多东西,做了那么多项目,但真要写简历或者回顾成长路径时,记忆总是模糊的。今天学了…...
GoAmzAI:开源本地化部署,AI赋能亚马逊卖家高效生成运营文案
1. 项目概述:一个面向亚马逊卖家的AI助手最近在和一些做跨境电商的朋友聊天,发现他们每天花在亚马逊店铺运营上的时间,很大一部分都耗在了重复性的文案工作上。从产品标题、五点描述、A页面,到广告文案、客户邮件回复,…...
