【问题标题】:Slam valve pattern大满贯阀门模式
【发布时间】:2015-05-06 16:35:51
【问题描述】:

在过去的几十年里,我见过很多次的事情是 slam valve 类型代码,其中有一个人为的值,一旦某个值被破坏,它就会递减/递增以强制循环退出,或者在某些情况下迭代已经过去。

对你来说有点抽象?

一些具体的例子:

文件读取

在这种情况下,文件在数据工厂中被读取过夜,因此需要在特定时间处理,以便系统在早上可用。注:文件是否完成并不重要。

int linesRead = 0;

const int SillyAmount = 1000000;

while (!EOF)
{
    text = ReadLine();
    // Do Some complicated processing with the text
    linesRead++;

    if (linesRead > SillyAmount)
        break;
}

服务对话

在此示例中,对象通过服务调用逐渐增强,直到数据足够好以便以后处理。

int conversationLines = 10;

while (conversationLines > 0 && conversation.Status != Complete)
{
    conversation.Next();
    // Process conversation
    conversationLines--;    
}

问题。

(1) 这种事情有设计模式或类似的吗?

(2) 在没有 (1) 的情况下,并且考虑到您人为地退出循环,这是否可以被视为代码异味?

【问题讨论】:

  • 好吧,Dijkstra 可能会抱怨第一个,但他抱怨大多数事情 ;) 使用 break; 而不是将所有循环退出条件限制在 while 表达式中会稍微难一些在循环之后的第一行代码中对世界状态做出保证,因为您必须通过循环体将所有break 可能性和|| 收集在一起。但通常情况下,试图将所有循环退出条件塞入while 表达式会使事情变得更加复杂。
  • “slam valve”是新的。我一直把它称为限制。
  • 我一直发现人们将这些事情称为节流(如果您是老派,则为限速)或分块
  • 我不会称之为模式,而是一种技术。

标签: algorithm design-patterns language-agnostic


【解决方案1】:

你的第一个例子可以写成:

int linesRead = 0;
const int SillyAmount = 1000000;

do {
  text = ReadLine();
  // text processing
} while (!EOF && ++linesRead <= SillyAmount);

这看起来不再像黑客了(不是break)。没有想到这个模式。

第二个留下了更多的解释(需要一个更完整的例子才能真正说明)。我们可以争辩说,对话对象也许应该设计为state machine(另请参见state pattern)并在内部处理对话以防止此类代码公开。要完成的实际处理可以作为(减少?)函数传递,或者根据预定义的对话类型使用某种strategy pattern 实现。有很多方法可以重新排列它。我们需要一个更现实的例子,因为这个例子有点奇怪(对话有迭代器(conversation.Next();)但行数在外面......可以告诉它处理到一定数量conversation.processUpTo(10);? )。

【讨论】:

    猜你喜欢
    • 1970-01-01
    • 2010-12-22
    • 1970-01-01
    • 1970-01-01
    • 1970-01-01
    • 1970-01-01
    • 2022-01-18
    • 2011-04-13
    • 2011-09-28
    相关资源
    最近更新 更多