Вы используете флаг или делаете две операции? - PullRequest
2 голосов
/ 17 июля 2009

Сегодня возникла интересная дискуссия о концепции наличия одного метода с флагами вместо двух методов для каждого состояния флага. Что имеет больше смысла и почему?

void Submit(object data, bool isDraft);

или

void Submit(object data);

void SubmitAsDraft(object data);

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

Что имеет больше смысла, и существуют ли общеизвестные правила или схемы, которые подсказывают, почему?

EDIT:

Предположим, что методы предоставляются как операции через Сервис SOAP, и концепции ОО не обязательно применяются. Хотя ОО является реализацией сервиса.

Ответы [ 11 ]

12 голосов
/ 17 июля 2009

Если вы используете одну функцию, не используйте bool, используйте enum:

enum DocType { Draft, Final };

void Submit(object data, DocType type );

Это имеет два основных преимущества - это самодокументирование на сайте вызова:

Submit( mydata, Draft );

и он расширяется естественным образом, если вы обнаружите, что у вас более двух типов документов (или статусов).

12 голосов
/ 17 июля 2009

Я бы сделал это:

void Submit(object data) { _Submit(data, false); }
void SubmitAsDraft(object data) { _Submit(data, true); }
(private) void _Submit(object data, bool isDraft);

Но это только я ...

5 голосов
/ 17 июля 2009

Какой из них более читабельный?

Submit(data, true); // true what?
// vs
SubmitDraft(data);

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

Submit(data, isDraft: true);
4 голосов
/ 17 июля 2009

Я лично иду на СУХОЙ; не повторяйся Если между ними много общего кода, используйте метод с флагом. В противном случае, два метода.

3 голосов
/ 17 июля 2009

Используйте такие понятия объектов, как полиморфизм; -)

data.submit()

с data, равным Draft или Final. Оба класса реализуют один и тот же интерфейс с помощью метода submit().

Таким образом вы избавляетесь от логических и ужасных данных структуры

3 голосов
/ 17 июля 2009

Другая альтернатива: иметь в качестве параметра enum {DRAFT, FINAL_VERSION}, а не логическое значение.

2 голосов
/ 17 июля 2009

Я бы сделал IsDraft свойством объекта, который вы передаете, так как он кажется относящимся к объекту.

1 голос
/ 17 июля 2009

почти все приведенные ответы верны, но, похоже, ни один из них не охватывает весь объем, поэтому -

  1. для очевидная семантика, два открытых метода:

    SubmitFinal (данные)
    SubmitDraft (данные)

  2. для минимальной реализации эти два открытых метода вызывают один внутренний метод:

    submitData (data, isDraft)

  3. для будущего расширения используйте enum вместо логического:

    submitData (data, DocType.Draft)

Присоединение перечисления к объекту данных еще лучше, если эта опция доступна, например,

data.DocType = DocType.Draft;
data.Submit();
0 голосов
/ 16 июля 2010

Я бы создал два отдельных метода:

void Submit(object data);
void SubmitAsDraft(object data);

Булевы параметры имеют привычку к рефакторингу в перечислениях, и их сложнее читать без поиска имени параметра формата.

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

0 голосов
/ 17 июля 2009

Я действительно разрываюсь на эту проблему. Я думаю, что использование второго метода более надежно и легче для отладки. Каждая функция становится очень четким черным ящиком. Ошибки легче отлавливать, потому что вы можете перехватывать входные ошибки внутри функции. Наличие флага вне области действия, кажется, вносит дополнительную двусмысленность в код. При каких условиях была вызвана моя функция? Где и почему был установлен мой флаг? Возникла ли логическая ошибка, из-за которой флаг был установлен неправильно? Это также заставляет вас проверять правильность флага, прежде чем вызывать функцию, которая может быть сложной. Я думаю, что удаление флага может привести к лучшей инкапсуляции внутри функции, и обработка ошибок состояния может последовательно решаться внутри функции.

Но, как я уже сказал, я разорван, первый метод может быть действительно удобным, и если у вас действительно сложная логика внутри функции, она может обеспечить согласованность из-за СУХОГО. Не нужно повторять действительно хрупкие и сложные функциональные возможности.

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

Также, помимо флагов, иногда я хочу знать, кто и что вызывает мою функцию. Поэтому иногда я добавляю ссылочный идентификатор в качестве дополнительного параметра.

void Submit(object data, bool isDraft, string referenceId);

Тогда я смогу узнать больше о том, кто вызывает submit, и может немного упростить отслеживание ошибок, если вы захотите навязать правила о том, кто должен вызывать вашу функцию и понимать, когда в логическом потоке она вызывается.

...