eiffel:断言开启时显式执行代码的语句

eiffel: a statement for explicitly executing code when assertions are on

有时检查和合同构造需要详细说明,当删除断言以提高性能并避免使用编译器的“唯一”工作做无用的事情时,希望避免这种情况。我指的是前任。循环检查或其他事情。有时不得不构建一个函数,或者不得不考虑如何构建它而不在断言开启时被执行,这与契约的直观方式及其意义背道而驰。我特别提到 check 结构

有没有办法做一些事情,例如

if checks_are_enabled then
    do check stuff here
end
do_some_normal_job
if checks_are_enabled then
    do other check stuff here
end

断言可以在 class-by-class 的基础上打开和关闭,具有不同的级别:先决条件、后置条件、不变量等。因此,在启用或关闭断言时进行报告会很棘手且不可靠不是(例如,考虑继承的代码:检查可能在一种情况下打开而在另一种情况下关闭)。在方法论层面上,它也打破了正确的程序以相同的方式工作而不管断言监控的想法。

有什么解决方法?

  1. 如果断言很复杂,它们可以被分解成专门的查询,看起来像

    check
        is_valid: complex_query
    end
    
  2. 另一种方法是使用调试语句:

    debug ("check_this", "check_that")
        ... some complex code, including assertions
    end
    

    其中"check_this""check_that"是调试键,编译调试时可以打开

  3. 有些技巧现在可以用,但将来不行:

    • 如果需要计算一个复杂的状态,然后在一些操作后检查,可以将它保存在一个对象中传递给一些复杂计算的函数,稍后再次使用:

      check
          is_valid_before: valid_pre (state) -- The state is computed by `valid_pre`.
      end
      code_that_does_the_work
      check
          is_valid_after: valid_post (state) -- The state is checked by `valid_post`.
      end
      
    • 一些全局标志可用于跟踪断言监控:

      check
          is_monitoring_checks
      end
      

      其中查询 is_monitoring_checks 有副作用:

      is_monitoring_checks: BOOLEAN
              -- Record whether assertion checks are turned on.
          do
              is_check_on := True
              Result := True
          end
      

      那么后面的代码就可以按照问题中的要求来写了:

       if is_check_on then
           ... -- Do some complex calculations when assertions are turned on.
       end