Due to the simplicity, however, assertions are sometimes viewed as a too primitive error-checking mechanism—something that’s perhaps good enough for smaller programs, but must be replaced with a “real” error handling in the industry-strength software. This view is inconsistent with the DbC philosophy, which regards contracts (assertions in C/C++) as the integral part of the software design. Contracts embody important design decisions, namely declaring certain situations as errors rather than exceptional conditions, and, therefore, embedding them in large-scale, industry-strength software is even more important than in quick-and-dirty solutions. Imagine building a large industrial electrical circuit (say, a power plant) without fuses.
然而,由于其简单性 , 断言有时被认为是一种过于原始的错误检查机制--对于较小的程序来说,这种机制也许足够好,但在具有工业强度的软件中,必须用 "真正的 "错误处理来代替 。这种观点与 DbC 哲学不一致 , DbC 哲学认为契约(C/C++中的断言)是软件设计的组成部分 。契约体现了重要的设计决策,即把某些情况宣布为错误,而不是异常,因此,把它们嵌入到大规模的、具有工业强度的软件中,甚至比快速和肮脏的解决方案更重要 。想象一下,在没有保险丝的情况下建造一个大型的工业电路(比如说,一个发电厂) 。Defensive or Preemptive Programming?防御式还是进攻式编程?
The term “defensive programming” seems to have two complementary meanings. In the first meaning, the term is used to describe a programming style based on assertions, where you explicitly assert any assumptions that should hold true as long as the software operates correctly.3 In this sense, “defensive programming” is essentially synonymous with DbC.
术语 "防御性编程 "似乎有两个互补的含义 。在第一种含义中,这个术语被用来描述一种基于断言的编程风格,在这种风格中,你明确断言任何假设,只要软件运行正常 , 这些假设就应该是真实的 。在这个意义上,"防御性编程 "基本上是 DbC 的同义词 。In the other meaning, however, “defensive programming” denotes a programming style that aims at making operations more robust to errors, by accepting a wider range of inputs or allowing an order of operations not necessarily consistent with the object’s state. In this sense, “defensive programming” is complementary to DbC. For example, consider the following hypothetical output Port class:
然而,在另一种意义上,"防御性编程 "指的是一种编程风格,旨在通过接受更广泛的输入或允许不一定与对象的状态一致的操作顺序,使操作对错误更加稳健 。在这个意义上,"防御性编程 "是对 DbC 的补充 。例如 , 考虑下面这个假想的输出端口类:
class Port {bool open_;public:Port() : open_(false) {}void open() {if (!open_) {// open the port ...open_ = true;}}void transmit(unsigned char const *buffer, unsigned nBytes) {if (open_ && buffer != NULL && nBytes > 0) {// transmit nBytes// from the buffer ...}}void close() {if (!open_) {open_ = false;// close the port ...}}// . . .};
This class is programmed defensively (in the second meaning of the term), because it silently accepts invoking operations out of order (that is, transmit() before open()) with invalid parameters (e.g., transmit(NULL, 0)). This technique of making operations more robust to errors is often advertised as a better coding style, but unfortunately, it often hides bugs. Is it really a good program that calls port.transmit() before port.open()? Is it really OK to invoke transmit() with an uninitialized transmit buffer? I’d argue that a correctly designed and implemented code should not do such things, and when it happens it’s a sure indication of a larger problem. In comparison, the Port class coded according to the DbC philosophy would use preconditions:这个类的编程是防御性的(在这个术语的第二个含义中),因为它默默地接受以无效的参数(例如,transmit (NULL, 0))不按顺序调用操作(即在 open () 之前调用 transmit ()) 。这种使操作对错误更健壮的技术经常被宣传为更好的编码风格,但不幸的是,它经常隐藏着错误 。在 port. open () 之前调用 port. transmit () 真的是一个好程序吗?用一个未初始化的发送缓冲区调用发送 () 真的可以吗?我认为,一个正确设计和实现的代码不应该做这样的事情 , 当它发生时,肯定是一个更大的问题的迹象 。相比之下,根据 DbC 理念编码的 Port 类会使用前置条件:
class Port {bool open_;public:Port() : open_(false) {}void open() {REQUIRE(!open_);// open the port ...open = true;}void transmit(unsigned char const *buffer, unsigned nBytes) {REQUIRE(open_ && buffer != NULL && nBytes > 0);// transmit n-bytes// from the buffer ...}void close() {REQUIRE(open_);open_ = false;// close the port ...}// . . .};
推荐阅读
-
-
-
-
-
-
-
-
-
-
-
-
-
-
-
-
-
-
-
-
- 《英雄联盟》英雄亚索怎么玩(各个英雄如何评价亚索)
- MySQL数据库的性能分析 ---图书《软件性能测试分析与调优实践之路》-手稿节选
- 《新录用公务员任职定级规定》咨询 新录用公务员任职定级规定2019
- 《正义联盟》中超人是怎么死的
- 《正义联盟》超人那么厉害,是怎么死的(正义联盟超人实力怎样)
- 《三国演义》中曹操的大将许褚是怎么死的(三国许褚做了哪些大事)
- 33 《吐血整理》高级系列教程-吃透Fiddler抓包教程-Fiddler如何抓取WebSocket数据包
- 《火影忍者》:二代火影真正的死因是什么为什么说是不会解开的迷题
- JVM运行时数据区域详解
- 《火影忍者》里,二代火影是怎么死的(二代火影为什么打不过金银角)