清晰,专注,自我记录的方法,无需重复

时间:2011-04-23 10:23:33

标签: design-patterns coding-style

这是一种经常出现的情况,对我来说永远不会太容易。我以为我会问别人怎么处理它。

想象一下,如果像这样处理 demo = 60 命令行参数:

if DemoOptionSpecified() {
  timeout = ReadInDemoTimeout();
  DoDemoVersion(timeout);
} else
  DoRealVersion();

DemoOptionSpecified()对参数字符串执行某种grep并返回true或false。

ReadInDemoTimeout()也会执行某种grep,相同的字符串,并返回一个整数。

两个greps做了两件不同的事情,但当然只需要一个grep来做两件事。两个greps而不是一个可能无关紧要,但在其他情况下,可能会有两个数据库或Ajax调用。

我并不特别喜欢让DemoOptionSpecified()做更多的事情而不是查看是否提供了该选项。方法名称不会建议额外捕获值。

我不特别喜欢让一个名为ReadInDemoTimeout()的方法如果demo选项不存在则返回false的替代方法,因为我只想知道设置选项时的超时值。 DoRealVersion()不关心超时值。

我觉得这没有一个好的不妥协的清洁代码模式。想法?

2 个答案:

答案 0 :(得分:2)

我没有看到有两种方法同时存在任何问题 - 你只需要正确命名它:

DemoOption demoOption = getDemoOption();
if (demoOption.wasSpecified()) {
    int timeout = demoOption.getValue();
    doDemoVersion(timeout);
}
else {
    doRealVersion();
}

你甚至可以使它更简单,让方法返回值,如果没有设置选项,则返回null:

Integer demoTimeout = getDemoOptionIfSpecified();
if (demoTimeout != null) {
    doDemoVersion(demoTimeout);
}
else {
    doRealVersion();
}

然后我将该方法设为通用目的:

Integer demoTimeout = getOptionIfSpecified("demo", Integer.class);
if (demoTimeout != null) {
    doDemoVersion(demoTimeout);
}
else {
    doRealVersion();
}

我不认为这是一种做两件事的方法。它做的一件事是“如果有一个选项,就获得选项的价值”。然后你可以问两个关于结果的问题 - 有一个问题,它有什么价值? - 但这发生在调用代码中。

如果你坚持不提取价值,除非需要,注入它怎么样?

interface OptionHandler<T> {
    public void specified(T optionValue);
    public void notSpecified();
}

handleOptionIfSpecified("demo", new OptionHandler<Integer>() {
    public void specified(Integer timeout) {
        doDemoVersion(timeout);
    }
    public void notSpecified() {
        doRealVersion();
    }
});

但是说真的,如果我正在阅读你的代码而我看到的不是第三个版本,我会看到过度复杂并开始重构。推测性地获取值并以不同方式处理null和非null情况的习惯用法非常普遍(至少在Java中);没有任何有用的目的是通过避免它来追求一些名义上的纯洁。

答案 1 :(得分:1)

也许是这样的,例如使用C ++:

bool GetDemoOption(int &timeout);

int timeout;
if (GetDemoOption(timeout)) {
    DoDemoVersion(timeout);
} else {
    DoRealVersion();
}

这依赖于C ++能够通过引用轻松传回选项值。在具有严格的值传递语义(如Java或Python)的语言中,这有点尴尬。但是,在Python中,可以从函数返回多个值:

exist, timeout = GetDemoOption()
if exist:
    DoDemoVersion(timeout)
else:
    DoRealVersion()