【问题标题】:Clean, singly focused, self-documenting methods without repetition干净、专注、自我记录的方法,无需重复
【发布时间】:2011-04-23 10:23:33
【问题描述】:

这是一个经常出现的情况,对我来说永远不会太容易。我想我会问其他人是如何处理的。

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

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

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

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

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

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

如果演示选项不存在,我并不特别喜欢使用名为 ReadInDemoTimeout() 的方法返回 false 的替代方法,因为如果设置了该选项,我只想了解超时值。 DoRealVersion() 不关心超时值。

我不认为有一个好的不妥协的干净代码模式。想法?

【问题讨论】:

    标签: design-patterns coding-style


    【解决方案1】:

    我不认为有一个方法可以同时做这两个问题 - 你只需要正确地命名它:

    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 中);为了追求某种名义上的纯洁,避免它没有任何用处。

    【讨论】:

    • 第一个版本越来越接近,可能确实是满足我迂腐的最佳选择。您的第二个和第三个版本与我在 Greg 的评论中指出的相同——仅在设置了演示选项时才需要超时详细信息,因此理想情况下我希望将其封装在演示块中,以便代码可以快速扫描,没有视觉噪音。
    • 我将添加另一个更复杂的选项,可能会让您感到满意。
    • 是的,它让我很开心! :) 我追求的不是纯度,而是可以最快地阅读和理解的任何代码。当然,这是一个简单的例子,任何人都可以快速阅读任何内容(条形注入!)。我会让瘫痪的分析消散并睡在上面。
    【解决方案2】:

    可能是这样的,例如使用 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()
    

    【讨论】:

    • 您的 C++ 示例,超时仅与演示版本相关,因此我想将其隐藏或封装在处理演示的块中。与 Python 示例相同。此外,我从不热衷于多个返回值,尤其是在 PHP 等没有预先声明的语言中。
    猜你喜欢
    • 1970-01-01
    • 1970-01-01
    • 1970-01-01
    • 1970-01-01
    • 2013-09-06
    • 2015-02-13
    • 1970-01-01
    • 1970-01-01
    • 2016-04-07
    相关资源
    最近更新 更多