惯性聚合 高效追踪和阅读你感兴趣的博客、新闻、科技资讯
阅读原文 在惯性聚合中打开

推荐订阅源

有赞技术团队
有赞技术团队
cs.CV updates on arXiv.org
cs.CV updates on arXiv.org
P
Palo Alto Networks Blog
C
Cisco Blogs
The Hacker News
The Hacker News
T
Threatpost
S
Schneier on Security
K
Kaspersky official blog
Spread Privacy
Spread Privacy
博客园_首页
钛媒体:引领未来商业与生活新知
钛媒体:引领未来商业与生活新知
NISL@THU
NISL@THU
量子位
cs.CL updates on arXiv.org
cs.CL updates on arXiv.org
Google DeepMind News
Google DeepMind News
Security Latest
Security Latest
博客园 - 司徒正美
云风的 BLOG
云风的 BLOG
博客园 - 叶小钗
H
Hackread – Cybersecurity News, Data Breaches, AI and More
N
News and Events Feed by Topic
爱范儿
爱范儿
P
Proofpoint News Feed
C
CERT Recently Published Vulnerability Notes
Project Zero
Project Zero
Application and Cybersecurity Blog
Application and Cybersecurity Blog
Cisco Talos Blog
Cisco Talos Blog
GbyAI
GbyAI
cs.AI updates on arXiv.org
cs.AI updates on arXiv.org
Apple Machine Learning Research
Apple Machine Learning Research
T
Tenable Blog
Threat Intelligence Blog | Flashpoint
Threat Intelligence Blog | Flashpoint
V
Vulnerabilities – Threatpost
Forbes - Security
Forbes - Security
博客园 - 三生石上(FineUI控件)
C
Cyber Attacks, Cyber Crime and Cyber Security
N
News and Events Feed by Topic
V
V2EX
Webroot Blog
Webroot Blog
The Register - Security
The Register - Security
OSCHINA 社区最新新闻
OSCHINA 社区最新新闻
阮一峰的网络日志
阮一峰的网络日志
freeCodeCamp Programming Tutorials: Python, JavaScript, Git & More
Blog — PlanetScale
Blog — PlanetScale
M
MIT News - Artificial intelligence
Scott Helme
Scott Helme
Simon Willison's Weblog
Simon Willison's Weblog
L
LangChain Blog
W
WeLiveSecurity
Cloudbric
Cloudbric

博客园 - 南柯之石

用户中心 - 博客园 自引用泛型模式分析 一定间隔时间下重复执行一个函数的几个方法 为什么.NET Framework就没有个专门的P/Invoke Library? Which would you perfer? "easy and fast and works well" or "hard and time consuming and error prone" 在ListView的GroupItem头中显示每列的Summary 小例子背后的大道理——用户需求+设计原则+正确应用 =设计方案 GET和POST有什么区别?及为什么网上的多数答案都是错的。 小例子背后的大道理——Adapter模式详解 小例子背后的大道理——从DIP中“倒置”的含义说接口的正确使用 XmlSerializer, DataContractSerializer 和 BinaryFormatter区别与用法分析 使用WPF开发的扫雷游戏,双系统主题复刻版 从一个UI交互设计师的讲座说开去 NoSQL和MemeryCache的出现意味着传统数据库使用方式的变革吗? 不使用反射进行C#属性的运行时动态访问 一次模块划分的争论及其结局 电子书籍质量保证事件分析 在SQL Server中调用.NET程序集 T-SQL 操作XML示例
技术误用带来的技术偏见及所谓的“经验”
南柯之石 · 2012-03-18 · via 博客园 - 南柯之石

从触发器说起

之前写了一篇NoSQL和MemeryCache的出现意味着传统数据库使用方式的变革吗?,里面描述了一下目前所在项目的数据库使用的情况————基本就是把SQL Server当成一个可自定义结构的文件在用。没有使用到任何数据库自身的特性,比如外键、约束、存储过程、触发器、自定义函数等。原因是我们的领导根据自己的经验,认为这些东西带来的麻烦大于好处,所以干脆就不要用。

不少人回复的意思都是,这是经验之谈,我应该Follow。其实我很震惊,怎么会有人觉得这样的经验是正确的?如果这个经验是正确的,那数据库系统早就没有这些东西了。然而事实却是,一些原本没有存储过程,没有触发器机制的数据库系统,却也在引入这些东西。

我不想在这里纠结应该不应该用触发器,这个问题讨论清楚了,还会有其它同样的问题出现。我想探究一下人们产生这种“经验”的原因,以及这种经验的误用。

技术特性的适用范畴

每项技术特性的出现都不会是为了娱乐,都是为了解决特定的问题。而且在设计、实现这项新特性的时候,设计者一般都会尽量地让这个特性更加地通用,更加地灵活,可扩展性更好。但是这些灵活性也会带来一系列的麻烦,其中之一就是对特性的误用。引用一句名言,一个API,如果有可能被误用,就一定会被误用。而且现实中这种误用的例子太多了。误用分两种,下面分别解释一下。

功能误用

一项技术,和这个技术可以解决的问题,会存在下图所示的关系。

image

如果开发者用一个技术去解决本不应该用这个技术解决的问题,结果可能会是处处碰壁,不是编码复杂就是性能差什么的。然后开发者就回来否定了这项技术,认为这技术一无是处。这种误用基本天天都在发生,并误导着一群人。如果某个大牛给出的什么建议,依赖到了自己这样的经验,而读者又存在盲目的个人崇拜心理,那这个误导人的建议,就很容易蔓延开来。

还是触发器为例,就连教科书上,都可以看到这样误用的例子。

有一个学生选课情况表,字段有学号、课程号、平时成绩、考试成绩、总评成绩。需要设计一个触发器,当学生的平时成绩或考试成绩修改时,就自动按照平时成绩20%和考试成绩80%的比例计算出总评成绩。

关于这个误用的解释,可以参考审慎而明智地使用SQL触发器

牛人高纳德的建议带来的误导

如果各位觉得国内教科书很山寨,我再举一个我个人觉得是误导的例子。著名计算机科学家Donald Ervin Knuth,在他的《计算机程序设计艺术》中提倡函数单入单出。有人就会拿来奉为金科玉律。却无视其提出这个建议时的社会环境、编程语言、编程思想的约束,要求C#,Java这样的语言写的函数也只能有一个return语句,我觉得就是很可笑的事情了。类似的带有误导性的建议还有很多,诸如要求源代码只能有80列,类名以DAL、BLL结尾之类。

实现误用

还有一种误用,就是这个技术功能用对了地方,但是实现方式不正确,结果也没有达到预期的目的。

以C#的Expression Tree和反射的使用方式为例,我也是刚看到又一个误用的例子。颠覆常识??Reflection、Delegate、Expression 生成实体类,实测结果,反射最快。显然就是没有正确使用Expression Tree的例子,这篇文章一度是博客园的评论头条,却也一直没有人指出问题的症结在什么地方。

最要命的当属各类这种建立在“实现误用” 之上的测评。网上各种Java、C#甚至C++程序员写的抨击对方性能差的文章中,测试结果彼此冲突的情况屡见不鲜。盖其原因,多数不过是对对方技术的“实现误用”。

2012年5月4日更新:

刚才又看到一个例子,编程经验点滴----避免在数据库访问函数中使用 try catch,LZ陈述了在DAL层使用try catch时存在的潜在问题,并提出了解决方案A。方案A的要点是不能在DAL中使用try catch,于是LZ就得出结论说所有的DAL中都不能使用try catch。我且不说他的结论是否正确,单纯的这种以偏概全的推理逻辑就是不合理的。因为可能存在方案B,在解决了问题的同时,并不要求DAL不能使用try catch。

经验带来技术偏见

再回来讨论之前触发器的问题。很多人抱怨触发器的原因就是性能、可移植性、复杂性。从他的抱怨其实就可以看出,他已经误用了触发器。而他失败的误用经历,让他对触发器本身产生了偏见。虽然其中的可移植性的确是个问题,但是如果你的产品从一开始就能决定就使用SQL Server,而且不会更换,那这也不是什么问题。如果你们的产品的确要做数据库兼容,那当然另当别论。

有人会说,我不用触发器也能达到我想要结果,为什么要用触发器?甚至还引经据典地用敏捷开发的理念来解释,说这是简化开发流程,简化开发环境。我有点儿想笑了,当有工具和环境专门给你解决你要解决的这个问题,你不去用,非要找一个不是解决这个问题的技术来Workaround一把,还说这是简单,我看是懒得学习或是技术歧视主义者罢了。

我的意思当然也不是某个系统自带了解决了X问题的技术,就一定要用这个技术去解决X问题。但是在否定这个技术前,请先确认你的技术方案比原有更好(更好编码,性能更好,可维护性高,任何一条都可以),千万不要“简单地试用了一下”就下结论说,我们重要自己做一套。这是对资源的极大浪费。

面对技术特性应当有理性的态度

各种技术特性就好比瑞士军刀,你当然可以用里面的主刀开瓶盖或是拧螺丝,但是不要因此抱怨瑞士军刀不好用,因为你根本没有用对地方。更糟糕的情况是,如果你是瑞士军刀的老板,希望你不要因此决定停止生产瑞士军刀。

所以当你发现一个技术功能没有达到你想要结果时,请先不要否则这项技术,请先问问自己下面这两个问题。

  1. 你所选择的技术是否适用于解决这个问题。(不要把某项技术用在不恰当的地方)
  2. 你的实现方式是否正确。(用某项技术,要用正确的方式使用。用对。)

完全地否定或是完全地肯定某项技术都是不理智的。都是一种类似种族歧视般的偏见。(请不要误解这句话,如果你说Asp.NET在各个方面都好过CGI,我也没有任何意见,这是技术进步的结果,而不是你对CGI有偏见。希望大家也能正确理解文章的主旨,不要纠结于字词的表面意思,一句句这样解释很累。)

针对你所喜欢的技术方案也是这样。也不要片面地觉得什么方案是万灵丹,在上一个项目成功了,在一个新的项目上就不会出问题。比如,你可能觉得在代码里拼SQL已经可以解决所有问题,这的确也没什么错。给足够多的时间,无论用什么方法都可以实现需求。但是技术进步的源动力是寻求更好的方案,不是吗?(可能又要有人拿技术的商业目的来说事儿,说赚钱就行,技术是屎,反正做出来就行,云云。那其实你就不应该进来来看这篇文章,不是吗?)