84. 在状态中思考

来源:互联网 发布:锐思数据库 编辑:程序博客网 时间:2024/05/01 16:59

在状态中思考

        现实世界中的人们对和状态有一种奇怪的关系。今天早上我在本地一家商店停下来准备将咖啡因转换为代码。由于我喜欢的方式是喝拿铁,然而我又找不到牛奶了,于是向店员询问。
        “抱歉,我们超级没有牛奶了。”
        对于程序员来说,这是个奇怪的表述。你要么就是有牛奶,要么就是没有。没有牛奶是没有尺度衡量的。也许她是想告诉我他们可能几个星期都没有牛奶了,但结果是一样的:今天只能喝浓咖啡了。
        在现实情况中,人们表述一个问题时往往漫不经心。但不幸的是,很多程序员也对状态搞不清楚,这就是问题了。
        考虑一个使用信用卡付款并不开发票的简单的网上商店,使用了一个包含了如下方法的订单类:

public boolean isComplete() {     return isPaid() && hasShipped(); }

         很合理,是不?即便这个表达式已经很好地放入了一个方法中,而不是复制粘贴得到处都是,但这个表达式根本就不该存在。事实上,它高亮了一个问题。为什么?因为订单在支付之前不可能发货。因而,除非isPaid已经是true了,hasShipped不可能是true,这就让这个表达式的一部分成了冗余了的。也许你仍然需要isComplete来让代码更清晰,但它看起来就像是这样了:

 public boolean isComplete() {     return hasShipped(); }

        在我工作中,我一直能看到丢失的检查和冗余的检查。这个例子很小,但当你增加了取消和重新支付时,它就变得更复杂了,需要处理的状态也就增加了。在这个例子中,一个订单只可能是三个不同的状态之一:
        处理中:可能增加或者移除物品。不能发货。
        已支付:不能添加或者移除物品。可以发货。
        已发货:完成。不能再改变。
        这些状态很重要,你在做任何操作前需要检查是否在预期的状态中,且只能转换到合法的状态。简单点说,就是要在正确 的地方仔细保护你的对象。
        但是如何开始在状态中思考?将表达式提出到一个有意义的方法是一个很好的开始,但只是个开始。基础是理解状态机。也许你有来自CS类的可怕记忆,但忘掉它们吧。状态机并不是特别难,将它们画出来就更容易理解和谈论。测试驱动你的代码,区分可用的和不可用的状态和转换并保持正确。学习状态模式。当你觉得合适时,按契约式设计,它可以让你通过在每个公共方法的输入和输出点对输入的数据和对象自我检查 ,就能确保可用的状态。
        如果你的状态不正确,就有bug,而且如果不终止的话,就会有垃圾数据的风险。如果你觉得状态检查太麻烦,学习如何使用工具、代码生成来隐藏它们。不管你使用什么方法,在状态中思考会让你的代码更简单、更健壮。

原文:Thinking in States byNiclas Nilsson


0 0