Возвращать или не возвращать из метода конкретный класс, а не интерфейс
От: Dziman США http://github.com/Dziman
Дата: 28.01.14 21:05
Оценка:
Столкнулся тут с такими принципами:
— метод должен принимать параметры как можно более общего типа
— метод должен возвращать объект как можно более конкретного класса

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

Рассмотрим на примере (здесь и далее Java, хотя это особого значения вроде как и не имеет)
'Классический' вид:
List<String> getNames(Long parentId, List<String> params) {
   List<String> result = new ArrayList<String>(20); // нам доподлинно известно что будет не больше 20 элементов
   // заполнение result
   return result;
}


'Конкретный' вид:
ArrayList<String> getNames(Long parentId, List<String> params) {
   List<String> result = new ArrayList<String>(20); // нам доподлинно известно что будет не больше 20 элементов
   // заполнение result
   return result;
}


Модификатор доступа я умышленно опустил, чтобы остался повод для дискуссии применимо ли это для public или может только private методов. На мой взгляд общедоступные методы не должны ни в коем случае быть 'конкретными'.
Дальнейшие примеры и случаи для 'конкретного' вида.

Теперь вариант кода когда нам все равно конкретный класс или интерфейс в сигнатуре метода, 'не опасный':
void method1() {
    List<String> names = getNames(...);
}

void method2(List<String> names) {
  //делаем что-то
}

void method3() {
    method3(getNames(...));
}


Код 'средней опасноти':
void method1() {
    ArrayList<String> names = getNames(...);
    // делаем что-то, но за рамки интерфейса List не выходим. Но зачем тогда объявление names как ArrayList :) ?
}


Ну и на закуску, 'опасный' код:
void method1() {
    ArrayList<String> names = getNames(...);
    // делаем что-то
    names.trimToSize(); // специфический для ArrayList метод 
    // делаем что-то
}


И вот наступает момент, когда нам приходится менять в getName ArrayList на LinkedList.
— В случае 'не опасного' кода ничего менять не надо. Но тогда вопрос зачем в сигнатуре метода указывать конкретный класс?
— 'среднеопасный' код: меняем в коде имя одного класса на другое и больше ничего не надо делать. И опять вопрос: зачем и почему такое может понадобиться, если с интерфейсами был бы точно такой код?
— 'опасный код': в этом случае мы отгребаем за связность и нам приходится не только менять тип переменной, но и переписывать логику. Тут я могу придумать для чего так можно было сделать: например, для оптимизации когда известно, что конкретная рализация в данном случае будет эффективнее намного другой.

Резюмируя все примеры и мысли:
Возвращать конкретный класс, а не интерфейс в общем случае скорее вредно, чем полезно и применять такой принцип для всех методов лучше не стоит.
Не упустил ли я какую-то деталь, которая доказывает полезность 'конкретного' принципа?
avalon 1.0rc3 build 430, zlib 1.2.5
 
Подождите ...
Wait...
Пока на собственное сообщение не было ответов, его можно удалить.