你如何验证对象的内部状态? [英] How do you validate an object's internal state?

查看:117
本文介绍了你如何验证对象的内部状态?的处理方法,对大家解决问题具有一定的参考价值,需要的朋友们下面随着小编来一起学习吧!

问题描述

我很感兴趣,听了技术()你正在使用的,从它自己的角度来看,只能是因为糟糕的内部状态或不变违反失败的操作过程中,验证对象的内部状态。

I'm interested in hearing what technique(s) you're using to validate the internal state of an object during an operation that, from it's own point of view, only can fail because of bad internal state or invariant breach.

我主要关注的是C ++,因为在C#中官方和流行的方式是抛出一个异常,并在C ++中有不止一个的办法做到这一点(OK,不是真的在C#要么,我知道)。

My primary focus is on C++, since in C# the official and prevalent way is to throw an exception, and in C++ there's not just one single way to do this (ok, not really in C# either, I know that).

请注意,我的不可以说起功能参数验证,而更像是类不变完整性检查。

Note that I'm not talking about function parameter validation, but more like class invariant integrity checks.

例如,假设我们希望有一个打印机对象队列异步的打印作业。为了打印机的用户,该操作才能取得成功,因为一个异步队列结果在其他时间到达。那么,有没有相关的错误代码传达给调用者。

For instance, let's say we want a Printer object to Queue a print job asynchronously. To the user of Printer, that operation can only succeed, because an asynchronous queue result with arrive at another time. So, there's no relevant error code to convey to the caller.

不过到了打印机的对象,这个操作可以失败,如果内部状态是不好的,即类不变坏了,基本上是指:一个bug。该条件是任何感兴趣的打印机对象的用户不一定。

But to the Printer object, this operation can fail if the internal state is bad, i.e., the class invariant is broken, which basically means: a bug. This condition is not necessarily of any interest to the user of the Printer object.

我个人倾向于混合三种样式的内部状态验证,我真的不能决定哪一个是最好的,如果有,也只是其中之一绝对是最糟糕的。我想听听您对这些观点,并认为你共享任何在这个问题上你自己的经验和想法

Personally, I tend to mix three styles of internal state validation and I can't really decide which one's the best, if any, only which one is absolutely the worst. I'd like to hear your views on these and also that you share any of your own experiences and thoughts on this matter.

我用的第一个样式 - 更好的失败不是损坏数据可控的方式:

The first style I use - better fail in a controllable way than corrupt data:

void Printer::Queue(const PrintJob& job)
{
    // Validate the state in both release and debug builds.
    // Never proceed with the queuing in a bad state.
    if(!IsValidState())
    {
        throw InvalidOperationException();
    }

    // Continue with queuing, parameter checking, etc.
    // Internal state is guaranteed to be good.
}



我用第二种风格 - 更好的碰撞比数据损坏无法控制的:

The second style I use - better crash uncontrollable than corrupt data:

void Printer::Queue(const PrintJob& job)
{
    // Validate the state in debug builds only.
    // Break into the debugger in debug builds.
    // Always proceed with the queuing, also in a bad state.
    DebugAssert(IsValidState());

    // Continue with queuing, parameter checking, etc.
    // Generally, behavior is now undefined, because of bad internal state.
    // But, specifically, this often means an access violation when
    // a NULL pointer is dereferenced, or something similar, and that crash will
    // generate a dump file that can be used to find the error cause during
    // testing before shipping the product.
}



第三个样式我使用 - 更好的默默防守保释超过损坏数据出来:

The third style I use - better silently and defensively bail out than corrupt data:

void Printer::Queue(const PrintJob& job)
{
    // Validate the state in both release and debug builds.
    // Break into the debugger in debug builds.
    // Never proceed with the queuing in a bad state.
    // This object will likely never again succeed in queuing anything.
    if(!IsValidState())
    {
        DebugBreak();
        return;
    }

    // Continue with defenestration.
    // Internal state is guaranteed to be good.
}



我的评论的风格:

My comments to the styles:


  1. 我想我更喜欢第二种风格,这里的失败不是隐藏,只要访问冲突实际上会导致系统崩溃。

  2. 如果它不涉及不变NULL指针,那么我倾向于对第一种样式倾斜。

  3. 我真的不喜欢第三的风格,因为它会掩盖大量的漏洞,但我认识的人那喜欢它在生产代码,因为它创造了不崩溃强大的软件的假象(功能将只是停下来的功能,如在破打印机队列目的)。

  1. I think I prefer the second style, where the failure isn't hidden, provided that an access violation actually causes a crash.
  2. If it's not a NULL pointer involved in the invariant, then I tend to lean towards the first style.
  3. I really dislike the third style, since it will hide lots of bugs, but I know people that prefers it in production code, because it creates the illusion of a robust software that doesn't crash (features will just stop to function, as in the queuing on the broken Printer object).

你喜欢的任何这些或你有实现这一目标的其他方式?

Do you prefer any of these or do you have other ways of achieving this?

推荐答案

现在的问题是你如何测试你的软件组合的最佳考虑。

The question is best considered in combination with how you test your software.

重要的是,创下了破不变在测试过程中被提起为高严重性的错误,就像崩溃会。 。建立在开发过程中测试可以作出停止死亡和输出诊断

It's important that hitting a broken invariant during testing is filed as a high severity bug, just as a crash would be. Builds for testing during development can be made to stop dead and output diagnostics.

可以适当添加防御性的代码,而不是像你的风格3:你的的DebugBreak 将转储诊断测试版本,但仅仅是为开发一个破发点。这使得不太可能其中通过在无关的代码中的bug工作防止开发商的情况。

It can be appropriate to add defensive code, rather like your style 3: your DebugBreak would dump diagnostics in test builds, but just be a break point for developers. This makes less likely the situation where a developer is prevented from working by a bug in unrelated code.

可悲的是,我常常看到它做了另一种方式圆,其中开发商拿所有的不便,但测试突破的不变量建立启航。奇怪的行为错误的大量申请得到,这里实际上是一个错误是原因。

Sadly, I've often seen it done the other way round, where developers get all the inconvenience, but test builds sail through broken invariants. Lots of strange behaviour bugs get filed, where in fact a single bug is the cause.

这篇关于你如何验证对象的内部状态?的文章就介绍到这了,希望我们推荐的答案对大家有所帮助,也希望大家多多支持IT屋!

查看全文
登录 关闭
扫码关注1秒登录
发送“验证码”获取 | 15天全站免登陆