Конкретные типы или интерфейсы для возвращаемых типов? - PullRequest
6 голосов
/ 21 апреля 2010

Сегодня я пришел к фундаментальному парадоксу стиля объектного программирования, конкретных типов или интерфейсов.

Как лучше выбрать тип возвращаемого метода: конкретный тип или интерфейс?

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

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

Какое правило у твоего большого пальца?

Есть ли какой-либо принцип программирования для этого?


БОНУС : Это пример того, что я имею в виду ReadOnlyCollection или IEnumerable для предоставления коллекций элементов?

Ответы [ 3 ]

7 голосов
/ 21 апреля 2010

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

5 голосов
/ 21 апреля 2010

Мои эмпирические правила:

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

2) Даже если объявлен метод, возвращающий конкретный тип, я бы написал код вызывающим сторонам, чтобы по возможности использовать тип интерфейса:
InterfaceType i = xyz.methodThatReturnsConcreteType();.

3) Имеет ли значение собственный код вызова (внутренние и публичные API):

  • Если мне принадлежит код, вызывающий рассматриваемый метод (т. Е. Внутренний API), то тем больше у меня желания вернуть конкретный тип.
  • Если я не контролирую код, вызывающий этот метод (например, общедоступный API), то, скорее всего, вместо этого я буду возвращать тип интерфейса. Возвращение конкретного типа является обязательством, и, вообще говоря, чем меньше я обещаю, тем легче.

Другие соображения:

  • С интерфейсами тестирование может быть проще, поскольку я могу использовать фиктивный объект, который реализует интерфейс.
  • Есть шанс, что я захочу вернуть прокси-объект (теперь я действительно ищу оправдания)

В итоге

  • Я обычно возвращаю тип интерфейса , потому что я чувствую, что преимущества слабой связи перевешивают удобство полного доступа к конкретному типу.
  • Однако я не против перехода на возврата конкретного типа в каждом конкретном случае, когда удобство перевешивает преимущества слабой связи.
1 голос
/ 21 апреля 2010

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

public AccelerationResponse PressAccelerator(float force) {}

Скорее всего, вы захотите вернуть интерфейс, а не класс. Вы можете интерпретировать этот ответ по-разному в зависимости от определенных условий.

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

...