Желательно ли иметь интерфейс в качестве типа возврата? - PullRequest
5 голосов
/ 14 июня 2010

У меня есть набор классов с одинаковыми функциями, но с другой логикой. Однако каждая функция класса может возвращать несколько объектов. Можно ли установить тип возвращаемого значения в качестве интерфейса?

Каждый класс (все используют один и тот же интерфейс) делает это с различной бизнес-логикой.

protected IMessage validateReturnType; <-- This is in an abstract class

public bool IsValid() <-- This is in an abstract class
{
    return (validateReturnType.GetType() == typeof(Success));
}

public IMessage Validate()
{
    if (name.Length < 5)
    {
        validateReturnType = new Error("Name must be 5 characters or greater.");
    }
    else
    {
        validateReturnType = new Success("Name is valid.");
    }

    return validateReturnType;
}

Есть ли подводные камни при модульном тестировании типа возврата функции? Кроме того, считается ли плохим дизайном иметь функции, которые должны быть запущены для их успеха? В этом примере Validate () необходимо будет выполнить до того, как IsValid (), иначе IsValid () всегда вернет false.

Спасибо.

Ответы [ 4 ]

10 голосов
/ 14 июня 2010

Однако каждая функция класса может возвращать несколько объектов.Безопасно установить тип возвращаемого значения в качестве интерфейса?

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

Существуют ли подводные камни при тестировании модулем возвращаемого типа функции

Нет.

Кроме того, считается ли это плохим дизайном дляесть ли функции, которые нужно запустить, чтобы они преуспели?В этом примере Validate () должен быть запущен до того, как IsValid (), иначе IsValid () всегда будет возвращать false.

Это хорошо для работы с парадигмой объектно-ориентированного программирования, например, работас розетками.Обычно есть способ подключения, прежде чем вы можете отправлять и получать данные.

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

4 голосов
/ 14 июня 2010

Кроме того, считается ли плохим дизайном иметь функции, которые необходимо запускать для их успешного выполнения? В этом примере Validate () должен быть запущен до того, как IsValid (), иначе IsValid () всегда будет возвращать false.

Есть исключения, но в целом вам следует избегать создания такого рода API. Это называется «временной зависимостью», которая является просто причудливым термином «одна вещь должна происходить раньше другой». Проблема с временными зависимостями заключается в том, что они редко описывают себя. Другими словами, API не сообщает сам по себе, как он предназначен для использования. API, которые полагаются на временные зависимости, зачастую сложнее понять и использовать, чем аналогичный код.

В вашем примере я рассмотрел бы рефакторинг API со следующими целями проектирования:

  1. Избавьтесь от другого IsValid.
  2. Validate возвращает список ошибок валидации.
  3. Переопределить «success», чтобы Validate () возвращал пустой список без ошибок.

Если вам просто нужен IsValid, переопределите его, чтобы проверить # 3. Если вы хотите кэшировать результаты, чтобы вам не приходилось постоянно пересчитывать IsValid, рассмотрите возможность внедрения INotifyPropertyChanged и аннулирования кэшированного результата в PropertyChanged.

1 голос
/ 09 августа 2010

Возвращение интерфейсов в целом хорошо, потому что оно скрывает реализацию. (Конечно, не стоит прятать больше, чем нужно ...)

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

Я бы лучше добавил абстрактный метод IsValid() в IMessage, переопределил его в Success и Error и вызвал бы validateReturnType.IsValid() напрямую. Звучит больше ОО для меня. Сама цель ОО и виртуальных методов - избежать переключения регистра на основе типов, как то, что вы делаете в своем IsValid().

1 голос
/ 14 июня 2010

Хорошо иметь интерфейс в качестве возвращаемого типа, потому что ваш метод будет совместим с большим количеством типов сообщений.

Добро пожаловать на сайт PullRequest, где вы можете задавать вопросы и получать ответы от других членов сообщества.
...