Effective Java: Методы

Переходим к следующей главе книги.

Item 38. Проверяйте параметры на корректность.
Большинство методов и конструкторов имеют некоторые ограничения на передаваемые им параметры. Проверка корректности этих параметров позволяет обнаруживать проблемы как можно раньше, что облегчает её исправление.
Для публичных методов и конструкторов лучше всего сразу проверять параметры и кидать соответствующие exception-ы, если они некорректны. Обычно это бывают IllegalArgumentException, IndexOutOfBoundsException или NullPointerException. Ограничения на параметры и exception-ы, которые кидаются при их нарушении должны быть задокументированы.
Для неэкспортируемых (закрытых) методов и конструкторов вы, как автор пакета, сами отвечаете за корректность передаваемых параметров и должны использовать только assertions для их проверки.
Есть и исключения из этих правил. Одно из них - когда проверка корректности слишком сложна и затратна и она происходит неявно во время выполнения метода. Пример такой ситуации - сортировка списка Collections.sort(List), который может содержать несравниваемые элементы. Иногда в таких случаях полезно применять идиому перевода исключений (exception translation idiom), чтобы клиентский код всегда получал понятное исключение вроде IllegalArgumentException вместо того, которое порождается внутри закрытого кода.

Item 39. Делайте защитные копии (defensive copies), когда нужно.
Здесь название говорит сам за себя. Вообще, программировать нужно так, как будто все клиенты только и будут пытаться нарушить инварианты ваших классов.
Защитные копии - ещё одна причина использовать неизменяемые (immutable) объекты в качестве компонентов.

Item 40. Проектируйте сигнатуры методов внимательно.
Здесь собраны советы, не вошедшие в другие параграфы.
  • Выбирайте наиболее подходящие имена для методов.
  • Не нужно слишком много "удобных" методов. Для каждого действия, обеспечиваемого классом или интерфейсом, пишите ровно один полнофункциональный метод. Особенно это касается интерфейсов. Добавляйте укороченный метод только если он будет часто использоваться.
  • Избегайте большого числа параметров. Лучше всего, когда их не больше четырёх. Три способа уменьшить их количество: разбить метод на несколько, создать вспомогающий класс, группирующий часть параметров, использовать шаблон Builder.
  • В типах параметров предпочитайте интерфейсы вместо имплементирующих классов.
  • Предпочитайте двухэлементый enum вместо boolean-параметра, где возможно. Например, если конструктор класса Thermometer принимает параметр, определяющий единицу измерения температуры, то лучше единицы измерения засунуть в enum, нежели выбирать одну в случае true и вторую в случае false.

Item 41. Используйте перегрузку (overload) осторожно.
В отличие от переопределения (override), перегрузка работает контринтуитивно: выбор метода происходит во время компиляции, а не в рантайме. Поэтому перегрузку следует применять только там, где этот выбор очевиден. Лучше всего, когда все взаимоперегружающие методы имеют разное количество параметров.

Item 42. Используйте varargs разумно.
Varargs - аргументы переменной длины. При замене аргументов метода на varargs следует учесть все возможные последствия, поскольку некоторые не компилируемые ранее вызовы метода станут допустимыми. Кроме того, не стоит забывать о возможной потере в производительности. Один из вариантов обойти эту потерю - предоставить отдельные методы для 1, 2, 3, ... аргументов и отдельный с varargs.

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

Item 44. Пишите комментарии к каждому экспортируемому элементу API.
Вряд ли кто-нибудь станет с этим спорить. Про утилиту javadoc знают почти все, а этот параграф посвящает в основы документирования API для последующего её применения.

2 комментария:

  1. Хорошие советы! Насчет 43 пункта: очень удобно использовать методы класса Collections, например emptyList().

    ОтветитьУдалить