2009-05-25 3 views
4

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

Один из его пунктов было всегда возвращаются в определенные типы данных, как это возможно, особенно при возвращении коллекции, итераторы и т.д. Так что, как я понял, вместо того, чтобы вернуться, скажем, Collection<String>, вы должны вернуться HashSet<String>, если вы используете этот тип данных внутри метода.

Это меня смущает, потому что похоже, что он поощряет людей нарушать правила информации, скрывающиеся. Теперь, я понимаю это, когда говорю об аксессуарах, это четкий случай. Но, вычисляя и искажая данные, а уровень абстракции метода не подразумевает прямой структуры данных, я считаю, что лучше всего вернуть как абстрактный тип данных, насколько это возможно, если данные не разваливаются (я бы 't return Object вместо Iterable<String>, например).

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

ответ

0

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

+1

Да, в некоторых случаях есть веская причина в возвращении LinkedList. Но я бы изменил тип возврата, как только возникнет конкретная потребность, после хорошего рассмотрения, а не по умолчанию. –

+0

Это неправильный подход, вы всегда должны возвращать List. Если вы знаете, что клиенты будут удалять много из вашего списка, тогда разумно вернуть LinkedList. Возвращение конкретного типа, а не интерфейса, в большинстве случаев никогда не будет правильным. Методы заключаются в контрактах, и в контракте говорится, что им возвращается список X. Как список делает свою вещь несущественной. –

+0

Да, но что, если (например), клиент должен перебирать список? Сделав подпись (и, следовательно, документы), используйте LinkedList в качестве типа возврата, клиент знает, что они не должны рассматривать список как список произвольного доступа. Таким образом, даже если все списки имеют List.get (индекс int), они будут знать, чтобы избежать использования этого метода с возвращаемым списком. В принципе, указанный тип возврата должен предоставлять информацию, когда вызывающий абонент имеет законную необходимость знать. –

1

Не может найти какие-либо доказательства, подтверждающие мое утверждение, но идею/руководство, кажется:

Будьте снисходителен, насколько это возможно, принимая вход. Выберите обобщенный тип по специализированному типу. Это означает, что клиенты могут использовать ваш метод с различными специализированными типами. Таким образом, IEnumerable или IList в качестве входного параметра означают, что метод может работать с ArrayList или ListItemCollection. Это максимизирует вероятность того, что ваш метод будет полезен.

Будьте как можно более строгими при возврате значений. Предпочитайте, если возможно, специализированный тип. Это означает, что клиентам не нужно вторгаться или перепрыгивать через обручи для обработки возвращаемого значения. Кроме того, специализированные типы имеют большую функциональность. Если вы решите вернуть IList или IEnumerable, количество вещей, которые вызывающий может сделать с вашим возвращаемым значением, резко сокращается - например. Если вы вернете IList поверх ArrayList, чтобы получить количество возвращаемых элементов - используйте свойство Count, клиент должен опуститься. Но тогда такое понижение поражает цель - работает сегодня .. не завтра (если вы измените тип возвращаемого объекта). Таким образом, для всех целей клиент не может легко получить количество элементов, что приводит к написанию мирского шаблона (в нескольких местах или в качестве вспомогательного метода).

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

0

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

Кроме того, я понял бы это таким образом:

Возвращение в абстрактном типе данных, как это возможно = вернуться в конкретный тип данных, как это возможно

т.е. когда ваш метод должен возвращать любые данные коллекции тип возвращаемой коллекции, а не объект.

скажите мне, если я ошибаюсь.

0

Конкретный тип возвращаемого гораздо более ценным, потому что:

  1. уменьшает возможные проблемы с производительностью обнаружения функциональность с литьем или отражения
  2. увеличивает читаемость кода
  3. НЕ в самом деле, выставить больше, чем необходимо.

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

Необходимо ли только пересечь структуру? необходимо сортировать структуру? преобразовать его? клонировать его? Это вопросы, на которые может ответить только вызывающий, и, следовательно, могут использовать абстрактный тип. Вызываемая функция ДОЛЖНА предусмотреть все эти случаи.

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

1

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

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

@Gishu

Если апи требует, чтобы клиенты отливать сразу большую часть времени ваш дизайн попались. Зачем беспокоиться о возврате X, если клиенты должны отливать Y.

+0

На каком языке вы находитесь, где вам нужно придать более конкретный тип супертипу? –

+0

@Pete Посмотрите на комментарии Гишу, где он оценивает такой случай и рассказывает о IList & List. –

3

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

На мой взгляд, вы должны всегда возвращать список, а не LinkedList или ArrayList, потому что разница больше детали реализации, а не смысловая один. Ребята из Google collections api for Java, сделав этот шаг дальше: они возвращают (и ожидают) итераторы, где этого достаточно. Но они также рекомендуют возвращать ImmutableList, -Set, -Map и т. Д., Где это возможно, чтобы показать вызывающему, что ему не нужно делать защитную копию.

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

+0

Думаю, я согласен с этим. В основном, расскажите абонентам все, что им нужно знать, и не более того. Однако я могу не согласиться с вашим конкретным примером. В/некоторых/случаях вызывающему нужно знать, получают ли они ArrayList или LinkedList. У них очень разные характеристики производительности. –

+1

@Matthew Если эти отличия в производительности являются проблемой, то недостаточно знать конкретный тип, вызывающий должен иметь возможность выбрать его (например, путем передачи пустой коллекции). – starblue

+0

Я полностью согласен с starblue. –

Смежные вопросы