The Law of Leaky Abstractions 抽象漏洞定理

2024-04-02 22:08

本文主要是介绍The Law of Leaky Abstractions 抽象漏洞定理,希望对大家解决编程问题提供一定的参考价值,需要的开发者们随着小编来一起学习吧!


我们每天都在使用的Internet里有一个小魔法。就是internet基础协议里的TCP协议。

TCP传输数据是可靠的。具体说来:你通过TCP传输数据,那么,数据是肯定会传输成功的并且顺序不会乱也不会错误。

我们使用TCP协议来获取网页、发送电子邮件。就连骗人钱财的邮件它都准确的送到。好玩吧。

TCP的反面是不可靠的传输协议,名字叫IP。没有人会打包票数据一定送达,可能在到达之前就已经混乱了。你发了一堆消息,如果只有一半送达,请淡定,它们中好一部分可能顺序已经乱了,也有可能消息的内容变化了,天知道会变成什么,或者是:猩猩的照片、或者看起来就像是来自台湾的垃圾邮件的标题。

当然,最神奇的是:TCP是基于IP的。即:可靠的TCP传输数据是使用了不可靠的IP。

为了解释,想像这样一个素材,虽然有点可笑,但是道理是相通的。

假想我们把ac放到车里,准备从王府井送往鸟巢。

有些车在二环上就翻了,可怜的ac也没有了。有些ac在路上搞了非主流,把自己弄的面目全非,到了鸟巢也进不去了。大部分的ac由于走的路线不同,到的时候前前后后,混乱不堪。

现在我们新开一个快递服务:至尊快递。至尊快递担保:把ac送到,按顺序,完整的。神奇的事情是:至尊快递除了用靠不住的车和不确定的路线来送ac,就别无选择了。

至尊快递需要检查每一个到达的ac,如果变形了,就给王府井打电话,重发一个ac。如果顺序不对,就重新排队。

如果市区里出现外星人强行阻断交通,至尊快递就改道先去海子公园,在绕到鸟巢。并且,至尊快递也不告诉鸟巢外星人的事情。

对于鸟巢来说,好像ac就是比平常来的晚了点,但是,它们一定不知道外星人来捣乱。

这就是TCP的神奇之处。计算机科学家更喜欢把这个叫做“抽象”:把复杂的隐藏起来,让它看起来简单。其实,很多程式码都是基于“抽象”的。

什么是字符串库?这样的库让操作字符串就像操作数字一样。什么是文件系统?把存储bit位的磁盘封装起来,就像是分层的文件夹一样,文件夹里包含了单个的文件,这些文件由一个或多个字符组成。

回到TCP,之前我给你讲的假话,已经如天上的鸭子,飞过了(这里我是这样理解的,不知道原文的意思是不是这样),这个谎言让你快受不了了。我说过:TCP保证你的消息送达,其实,它做不到。

如果你的宠物蛇把你的网线咬断了,你的计算机就收不到IP包,这种情况下,TCP也不能做任何事情,你的消息也不会送达。

如果你骂楼主是SB,楼主把你的计算机配置到一个超载的HUB上,你的IP包只有随机通过了,TCP也可以工作,不过肯定是龟速了。

这就是我说的“抽象漏洞”。TCP想提供一个基于不可靠的网络的完全的抽象,但是,有时候,网络漏洞会越过抽象,你会说抽象也不能提供完全的封装(我是这样理解的).这只是我的抽象漏洞定理的一个例子:

所有不证自明的抽象都是有漏洞的。

抽象机制倒下了。有时是一点点,有时太多了。漏洞太多了,事情就不妙了。只要你拥有抽象,这种情况就会发生,如下:

操作二维数组的时候,横向或是竖向的操作性能是不一样的,就看在存储器里如何布局了。在按行操作或是按列操作的时候,有可能会导致页面访问失败,而这会是非常慢的。就算是在汇编程序里,可以认为有很大的线性的内存空间,但是,虚拟内存是一个抽象的概念,页失败的话这个抽象就失效了,这时候处理的时间会比其它的储存形式慢。

SQL语句就抽象了查询。你只需要定义你想要查找的,不用关心查找执行的细节。但是,有时候,SQL查询会比想象中的耗费时间。著名的例子就是:如果你的查询条件是“where a=b and b=c and a=c”会比查询条件是“where a=b and b=c”快,而这两者的结果是一样的。你只需要关心查询结果而非执行过程。但是,当抽象失效并且引起性能恶化的时候,你只有拆开查询分析器,研究到底神马情况,并且研究如何才能提升性能。

尽管网络库如:NFS、SMB可以让你操作远程的文件就像是在自己的计算机上一样。但是,如果网上变慢或是断线了,身为码农,你该咋办?把“远程文件映射到本地”的抽象失效了,在Unix里有活生生的例子:你把用户的home文件夹挂载到NFS的磁盘上(一个抽象),用户又创建一个.forward文件夹来把email转存到其它地方(又一个抽象),新邮件到达的时候,NFS刚好罢工了,由于它的罢工,挂载给它的文件夹也就找不到了,错误发生了,你的email都没有了。

C++ String类是希望你处理数组相对简单,就像是处理整型那样,它抽象了“字符串很难处理”。所有的C++ String类都重载了+操作符,这样你可以这样来连接两个字符串: s+"bar"。你知道吗:无论有多难,地球上就没有那个String类允许你这样:"foo" + "bar",因为C++里就没有语义上的字符串,它们其实是char*。这个抽象带来的漏洞你是没法补的。(有趣的是,C++的进化史就是补String抽象带来的漏洞的历史。他们为嘛不在C++里添加一个原生的字符串类?我不知道耶。)

下雨的时候,你不可以开太快,就算你有挡风玻璃有各种装备,这些装备可以让你忽略下雨这个事实(这些装备把天气抽象了),但是,你还是担心路滑(或是滑水效应),雨很大的时候,你看不远。你在雨里还是开车慢,因为天气不会被完全抽象,因为抽象漏洞法则真实存在。

抽象漏洞法则之所以是个问题,是因为这个抽象并没有期望的那么简单。当我教C++的初学者的时候,我不教他们char*及指针运算,直接教STL字符串。但是,总有一天他们会这样写:"foo" + "bar",或是奇怪的代码,我还是需要教他们char*。而且,某日他们需要搞明白:char*、指针、Unicode、wchar_t、TCHAR头文件,否则他们没法调用参数是 OUT LPTSTR 这样的window API,么么,这些都是漏洞。

教某人COM编程,告诉他们如何使用Visual Studio 向导、代码生成器,如果出了问题,他们就不知道如何处理,也不知道如何修复这个bug。我需要告诉他们IUnknown 、CLSIDs 、ProgIDS 等等。噢,不人道呀。

教ASP.NET编程,就告诉他们双击控件,然后就添加代码。而不是教他们ASP.NET在处理点击超链接和点击按钮有什么不同。ASP.NET的设计者需要隐藏HTML的外表(我的理解——译者),你不可以通过超链接来提交表单。他们在javaScript里实现,并且放到到onclick的处理代码里。抽象的漏洞。如果我们禁用了javaScript,程序就出错了,如果我们的码农不明白这个抽象原理,他们就无法指定问题到底在哪里。

抽象漏洞法则说明:任何时候,大牛发明了一个工具可以提高效率的时候。很多人说:“我先人工的操作,然后通过代码来节约时间”。代码生成工具就是这样想的,它抽象了一些东西,但是,所有的抽象机制都是有漏洞的。唯一可以处理漏洞的方法就是知道抽象的原理,都抽象了些什么东西。抽象可以节约我们工作的时间,但是,节约不了我们的学习时间。

这一切都似是而非,我们有更高级的编程工具,更好的抽象,然而成为专家就更难了。

我在微软实习的时候,我给Macintosh写了一个字符串库。一个常见的任务:写一个strcat函数,返回一个指向新字符串结尾的指针。几行代码。我做的事情记录于K&R(这是一本讲c语言的小册子)

如今,为了做CityDesk,我需要知道Visual Basic、COM、ATL、C++、 InnoSetup、 Internet Explorer internals、 正则表达式、DOM, HTML, CSS, and XML。但是,我还是需要知道K&R里的东西,否则我就完蛋了。

10年前,我们希望有一个更高级的编程范式可以让编程更简单。我们创造的抽象机制,让我们可以设计更复杂的软件,如:GUI和网络程序,在10年或是15年前是无法想像的。这些伟大的工具,如:OO编程语言,让我们飞快的工作,但是某天,我们为了排查一个抽象带来的漏洞,一查就是几个星期。你找一个写VB的码农,如果他只会单纯的写代码的话,当VB的抽象出现漏洞的时候,他就会傻眼。

抽象漏洞会拖垮我们。


原文地址:http://www.joelonsoftware.com/printerFriendly/articles/LeakyAbstractions.html


你也可以在这里看:http://blog.sina.com.cn/s/blog_5fcf62ff0101haar.html

这篇关于The Law of Leaky Abstractions 抽象漏洞定理的文章就介绍到这儿,希望我们推荐的文章对编程师们有所帮助!



http://www.chinasem.cn/article/871178

相关文章

uva 1342 欧拉定理(计算几何模板)

题意: 给几个点,把这几个点用直线连起来,求这些直线把平面分成了几个。 解析: 欧拉定理: 顶点数 + 面数 - 边数= 2。 代码: #include <iostream>#include <cstdio>#include <cstdlib>#include <algorithm>#include <cstring>#include <cmath>#inc

工厂方法模式和抽象工厂模式的区别

区别  工厂方法模式: 一个抽象产品类,可以派生出多个具体产品类。    一个抽象工厂类,可以派生出多个具体工厂类。    每个具体工厂类只能创建一个具体产品类的实例。 抽象工厂模式: 多个抽象产品类,每个抽象产品类可以派生出多个具体产品类。    一个抽象工厂类,可以派生出多个具体工厂类。    每个具体工厂类可以创建多个具体产品类的实例。    区别: 工厂方法模式只有一个抽象产品类

【CTF Web】BUUCTF Upload-Labs-Linux Pass-13 Writeup(文件上传+PHP+文件包含漏洞+PNG图片马)

Upload-Labs-Linux 1 点击部署靶机。 简介 upload-labs是一个使用php语言编写的,专门收集渗透测试和CTF中遇到的各种上传漏洞的靶场。旨在帮助大家对上传漏洞有一个全面的了解。目前一共20关,每一关都包含着不同上传方式。 注意 1.每一关没有固定的通关方法,大家不要自限思维! 2.本项目提供的writeup只是起一个参考作用,希望大家可以分享出自己的通关思路

Java验证辛钦大数定理

本实验通过程序模拟采集大量的样本数据来验证辛钦大数定理。   实验环境: 本实验采用Java语言编程,开发环境为Eclipse,图像生成使用JFreeChart类。   一,验证辛钦大数定理 由辛钦大数定理描述为: 辛钦大数定理(弱大数定理)  设随机变量序列 X1, X2, … 相互独立,服从同一分布,具有数学期望E(Xi) = μ, i = 1, 2, …, 则对于任意正数ε ,

Java反序列化漏洞-TemplatesImpl利用链分析

文章目录 一、前言二、正文1. 寻找利用链2. 构造POC2.1 生成字节码2.2 加载字节码1)getTransletInstance2)defineTransletClasses 2.3 创建实例 3. 完整POC 三、参考文章 一、前言 java.lang.ClassLoader#defineClass defineClass可以加载字节码,但由于defineClas

Java基础入门 【第七章 抽象、接口、内部类、枚举】(二)

匿名内部类书写格式: 父类或接口类型变量名=new父类或接口(构造方法实参列表){ //重写所有的抽象方法 @Override public返回值类型method1(形参列表){ 方法体实现 } @Override public返回值类型method2(形参列表){ 方法体实现 } //省略... }; //匿名内部类对象调用方法 变量名.重写方法(实参列表); 匿名

CPC23三 K.(Lucas定理)

K.喵喵的神·数 Time Limit: 1 Sec Memory Limit: 128 MB Description 喵喵对组合数比较感兴趣,并且对计算组合数非常在行。同时为了追求有后宫的素质的生活,喵喵每天都要研究质数。 我们先来复习一下什么叫做组合数。对于正整数P、T 然后我们再来复习一下什么叫质数。质数就是素数,如果说正整数N的约数只有1和它本身,N

【vulhub】thinkphp5 2-rce 5.0.23-rce 5-rce 漏洞复现

2-rec 1.启动环境  cd /.../vulhub/thinkphp/2-rce # cd进入2-rce靶场文件环境下docker-compose up -d # docker-compose启动靶场docker ps -a # 查看开启的靶场信息 2.访问192.168.146.136:8080网页 3.构造payload http

【漏洞复现】赛蓝企业管理系统 GetJSFile 任意文件读取漏洞

免责声明:         本文内容旨在提供有关特定漏洞或安全漏洞的信息,以帮助用户更好地了解可能存在的风险。公布此类信息的目的在于促进网络安全意识和技术进步,并非出于任何恶意目的。阅读者应该明白,在利用本文提到的漏洞信息或进行相关测试时,可能会违反某些法律法规或服务协议。同时,未经授权地访问系统、网络或应用程序可能导致法律责任或其他严重后果。作者不对读者基于本文内容而产生的任何行为或后果承担

【网络安全】Jenkins任意文件读取漏洞及检测工具(CVE-2024-23897)

原创文章,不得转载。 文章目录 漏洞成因影响范围检测工具更多细节 漏洞成因 Jenkins CLI 接口存在任意文件读取漏洞(CVE-2024-23897)。该问题源于 args4j 库在解析文件名参数时,会将@符号后的字符串视为文件名并尝试读取文件,而且该功能默认处于启用状态。 影响范围 Jenkins weekly <= 2.441 Jenkins LTS <=