“魔法”这个词在这里被广泛使用,例如“语言 X 有太多魔法”或“平台 Y 通常避免魔法”。然而,这个词的定义似乎很不明确,人们看到它就知道了。例如,Java 被认为包含的魔法很少,但它的垃圾收集器对程序员隐藏了很多东西。如果魔术只是意味着隐藏细节的抽象,那么既然没有人再用汇编语言编写大型程序,为什么它被认为是一件坏事呢?如果魔法意味着更多,那么它意味着什么?
13 回答
“任何足够先进的技术都与魔法无异”——Arthur C. Clarke。
实际上并不完全如此——魔法用于复杂和隐藏而不是高级(尽管可能设计者认为他们是高级的),例如在过程调用(COM 线程模型)之前需要特定状态的系统以及“自动”类型转换(VB 变体,Javascript ==,Java 自动装箱)。
一旦系统向程序员隐藏了无法预测的细节,它们就会变得神奇。你被困在用你不懂的语言重复调用,因为它在过去产生了正确的效果。那是坏魔法,或巫术。
还有很好的魔法——http: //aggregate.org/MAGIC/
当你忽略它/你不知道它是如何工作的时候,它就是魔法。
在微软,这往往有两种使用方式
1)以消极的方式(可能是最常见的用法)。例如,有人可能会说“我不明白;首先您将重构 API,然后您将保留旧 API 并在它们之间有一个执行魔术的层?”
这意味着魔法组件太复杂、太未定义或太“某事”。
另一种负面情况是当某些事情被天真地定义时:这通常发生在有人假设一个复杂问题有一个简单的解决方案时,因为他们没有意识到问题真的很复杂。 Raymond Chen 的博客充满了这类例子。
2)“魔法”一词很少被积极使用。但它确实发生了。有用地指代执行复杂任务的事物。对我来说,NTFS 就是那种魔法。NTFS 非常非常成熟,并且在一些非常简单的 API 后面隐藏了很多复杂性。编译器也可以通过这种方式被视为“魔法”——你真的深入了解 C++ 编译器的工作原理吗?我不 - 我只是相信他们会这样做。
魔术与您的理解非常相关。
在开始用 Java 编写之前,我写了相当多的 C 和 C++。我必须分配和释放我所有的内存。一旦我开始出现内存泄漏,这并不是很有趣。一旦我开始用 Java 编写代码,我就(基本上)知道幕后发生了什么,以便创建我的所有实例对象。因此,对我来说,它不像对开始使用 Java 的人那么神奇(我已经完成了分配,但它如何实际存储对象并知道何时释放它们对我来说更“神奇”) (谁从来没有手动处理内存。)
另一个例子是 ORM。我在项目早期推出了自己的临时对象关系映射结构,直到我有时间真正放下心来学习 Hibernate 或类似的东西。我必须编写诸如 ResultSet 映射器、延迟加载和一些基本缓存之类的东西。现在,当我回去用更成熟的 Hibernate 或 JPA 映射实体替换这些东西时,我仍然会对正在发生的事情有一个基本的了解。如果您从未使用过 JBDC 或类似的东西,那么您将真正知道的是数据从数据库到对象再返回。
每个人在他们的职业生涯中都会处理一定程度的魔法。我们不可能知道一切。魔术真的可以成为抽象的代名词。当它变得“太神奇”时,就是抽象开始掩盖你需要能够控制的东西。前几天的一个例子是,在一个 JSF 程序中,我不知道如何启动一个 JSF 上下文。JSF 只是在您第一次导航到 JSF 页面时执行此操作。我需要从常规 servlet 启动上下文。我最终不得不制作一个虚拟的 JSF 页面来处理它。我根本没有时间在这个项目中学习 JSF 上下文管理的“魔力”。
魔术具有与其他上下文相同的含义:具有隐藏的复杂性和逻辑的东西。这并不总是坏事,但对于程序员(非技术人员的魔术师)来说却是。当你(可以)知道它是如何工作的时候,魔法就不是魔法。
例如,魔术常量:具有隐藏含义的常量。
当我们谈论一些混淆代码中发生的“黑魔法”时,我们的意思是在这段代码中发生了一些我们不理解的事情;或者发生了一些非书面但对代码阅读器隐藏的事情。
在某些情况下,你会以积极的方式谈论魔法:当你看不到一个简单的东西的真正复杂性时,就很难理解如何使用它。例如,一些非常复杂的代码可以隐藏在一个很小且易于使用的接口类中。这看起来很神奇,因为它用简单的用法做复杂的事情。那是很好的魔法(但很少见)。
例如,Ruby on Rails 就是 Magic。
在基本层面上,尤其是当你天真地接近时,在你的极简代码和数据库之间有一层厚厚的一层,然后魔法发生了,你得到了粗鲁的功能和所有其他的东西。
有些人可以忍受那种非常高水平的体验,但最终你会开始遇到障碍,你需要了解“技巧”的“秘密”,这样你就可以更好地操纵它以达到你的目的。
语言本身并没有太多的魔力(好吧,也许 Prolog ——它的核心有点神奇),但现代框架和中间件可能充满了魔力。
坦率地说,每当你遇到一个系统或组件做“令人惊奇的事情”并且你想知道“他们是如何做到的”时,这就是魔法。
有趣的是:该术语magic
与形式编程语言相关,这是计算机科学的理论基础之一。在 Morgan 的《从规范编程》一书中,我们对魔法有这样的定义:
w:[true, false]
该符号的形式为:
w:[P, Q]
并表示一个程序,当在一个为真的状态下执行时P
,将在一个为真的状态下终止Q
,同时仅更改w
.
因此,在这种情况下,“魔术”是一个不可行的程序,它可以将程序从任何状态(因为true
总是true
)变成不可能的(因为false
永远不可能true
)。
一个更简单的程序是:
w:[true, true]
这是始终终止但不保证特定结果的程序。这可以通过一个简单的skip
.
显然,当人们谈论程序时,这个技术定义被滥用了magic
,因为这应该意味着一个可证明不可行的程序。尽管如此,这个术语仍然是通俗的,因为当我们不知道或不了解某事如何运作时,可以想象在幕后发生了一些神奇的事情。
当你不理解它时,你称它为“魔法”。
人们习惯于在中世纪做/知道/说一些其他人无法理解的事情时被烧死。他们被指控做“魔术”。
当您不了解代码/框架/语言的作用时,您将其称为“魔术”。称之为“魔法”比花时间去理解它更容易。
魔法不存在!
与其称某事为“魔法”,不如让你的手弄脏并了解那件事在做什么……或者称其为“(你的)知识中未探索的部分”。
对于 Java
- GC - 恕我直言,这不是魔法,就像有一个家庭清洁工
- 自动装箱 -魔法- 将某物隐形变形为其他东西
未知行为经常被称为魔术。有些事情没有明显的原因发生。
但也有不为人知的国王:
开发人员方面缺乏关于事物如何工作的知识。(例如 GC,它不是魔法,只是很少有开发人员真正费心去发现和理解它的基础)
未定义的行为魔术,事情发生在幕后,并且没有关于它们实际工作的公开知识。这是编程中真正的魔力。
例如 Rails,它不是魔法,而 Ruby 也不是魔法,但对于一些人来说,如果他们从不费心去理解内部结构(这是公共知识并且可用),他们肯定会看起来如此。
我使用术语“黑魔法”的一个上下文是字节码操作(在 Java 中)——在运行时转换程序代码,使其执行与普通代码不同的操作。很多时候,字节码操作非常有用,但也很容易用它来打自己的脚。
许多框架和中间件使用AOP和字节码操作来实现横切关注点。这减少了程序员的工作量,但在某些情况下,它可能会使调试系统行为变得困难。而且很容易在字节码转换中留下一些细微的错误。
我自己做了一些字节码操作,所以基本上我知道如何更改字节码指令,从这个意义上说,这对我来说并不是“魔法”,我不明白它是如何工作的。但我仍然将其称为“魔术”,因为它改变了代码正常工作的方式,并且在被更改的类的源代码中不可见。
有关黑魔法的一些不错的示例,请查看 perl 源代码中的文档;-)