Чистые, сфокусированные, самодокументируемые методы без повторений - PullRequest
2 голосов
/ 23 апреля 2011

Вот ситуация, которая возникает довольно часто, которая никогда не бывает слишком легкой для меня.Я думал спросить, как другие справляются с этим.

Представьте себе, если обработка аргумента командной строки demo = 60 была сделана так:

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

DemoOptionSpecified() выполняет какой-то grep для строки аргумента и возвращает true или false.

ReadInDemoTimeout () также выполняет некоторый вид grep, той же строки и возвращает целое число.

Два greps делаютдве разные вещи, но, конечно, только один grep необходим, чтобы сделать оба.Здесь может не иметь значения два greps вместо одного, но в других сценариях два вызова базы данных или Ajax могут иметь значение.

Мне не особенно нравится, когда DemoOptionSpecified () делает что-то большее, чем проверка, предоставляется ли опция.Дополнительный захват значения не будет предложен именем метода.

Мне не особо нравится альтернатива наличия метода ReadInDemoTimeout (), возвращающего false, если демонстрационная опция не существует, так как я хочу слышать только о значениях тайм-аута, если эта опция установлена.DoRealVersion () не заботится о значении тайм-аута.

Не думаю, что для этого есть хороший бескомпромиссный шаблон чистого кода.Мысли?

Ответы [ 2 ]

2 голосов
/ 23 апреля 2011

Я не вижу никаких проблем с наличием метода, который выполняет обе функции - вам просто нужно правильно назвать его:

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

Вы можете даже упростить его, и метод вернет значение,или ноль, если опция не была установлена:

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();
    }
});

А если серьезно, если я читал вашекода, и я увидел что-то кроме третьей версии, я бы увидел чрезмерное усложнение и начать рефакторинг.Фраза умозрительного получения значения и работы с нулевыми и ненулевыми случаями по-разному широко распространена (по крайней мере, в Java);никакая полезная цель не достигается, избегая ее в погоне за какой-то условной чистотой.

1 голос
/ 23 апреля 2011

Возможно, что-то вроде этого, например, с использованием 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()
Добро пожаловать на сайт PullRequest, где вы можете задавать вопросы и получать ответы от других членов сообщества.
...