var _gaq = _gaq || []; _gaq.push(['_setAccount', 'UA-333696-1']); _gaq.push(['_trackPageview']); _gaq.push(['_trackPageLoadTime']); (function() { var ga = document.createElement('script'); ga.type = 'text/javascript'; ga.async = true; ga.src = ('https:' == document.location.protocol ? 'https://ssl' : 'http://www') + '.google-analytics.com/ga.js'; var s = document.getElementsByTagName('script')[0]; s.parentNode.insertBefore(ga, s); })();
  • 2008年05月04日

    【翻译】可测性合约成为异常的邻居

    分类:

    原文链接

     

    考虑下列函数,它修改一个客户端对象:

    bool SomeCollection::GetObjects(vector* objects) const {
      objects->clear();
      typedef vector::const_iterator Iterator;
      for (Iterator i = collection_.begin();
            i != collection_.end();
            ++i) {
        if ((*i)->IsFubarred()) return false;
        objects->push_back(*i);
      }
      return true;
    }

    考虑当GetObjects()被调用。如果调用者不检查该返回值,并设想该数据是一个有效状态但实际不是的?如果调用者检查该返回值,它该怎样设想它的对象状态在用例失败情况下?当GetObjects()失败,这将更好如果所有或者没有一个对象被收集。这能帮助避免引入很难找到的错误。

     

    通过使用良好的设计合约和扎实的实施,很合理地容易使函数GetObjects()行为像事物。通过遵从Sutter的规则即修改外部的可视性状态仅当在完成所有可能失败的操作后[1],并混合Meyers的“swap把戏”[2],我们从未定义行为移向Abrahams定义的强保证[3]

    bool SomeCollection::GetObjects(vector* objects) const {
      vector known_good_objects;
      typedef vector::const_iterator Iterator;
      for (Iterator i = collection_.begin();
            i != collection_.end();
            ++i) {
        if ((*i)->IsFubarred()) return false;
        known_good_objects->push_back(*i);
      }
      objects->swap(known_good_objects);
      return true;
    }

     

    以一个临时和指针交换的代价,我们强化了像那样的我们接口的连系,最好,调用者接受一个完整的有效对象的新集合;最坏,调用者的对象状态保持不变。调用者可能无法验证此返回值,但不会面临为定义的结果。这允许我们更加清晰地判断程序状态,使它更加容易核实自动化测试的输出意图并在回归测试再创建,精确定位并驱逐bugs

     

    1.     http://www.gotw.ca/publications

    2.     Scott Meyers, Effective C++条款25swap成员函数不抛出异常

    3.     http://www.boost.org/more/generic_exception_safety.html

    分享到: