The Hidden Dangers of Method Overloading

The following text is a partial translation of the original English article, performed by ChatGPT (gpt-3.5-turbo) and this Jekyll plugin:

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

Давайте начнем с примера на языке Java. Предположим, вы хотите добавить товар в корзину, имея при этом либо идентификатор товара, либо объект Product. Если предоставлен только идентификатор, вы хотели бы, чтобы корзина обратилась к каталогу товаров, нашла соответствующий объект Product и добавила его. Вот где перегрузка методов может быть полезной (метод add() определен дважды с двумя разными сигнатурами и реализациями):

Этот подход действительно удобен по крайней мере по двум причинам. Во-первых, метод add(int) обрабатывает преобразование из int в Product, которое не нужно повторять в других местах - вместо этого можно просто передать ID товара в этот метод и позволить ему выполнить работу, тем самым устраняя дублирование кода. Во-вторых, поскольку функциональность “поиска в каталоге” не раскрывается за пределами класса Cart, это упрощает окружающий код. Кажется, что действительно улучшаются удобство использования и читаемость кода.

Однако решаемые проблемы (дублирование кода и сложность) меньше, чем вводимые проблемы. Если семантика метода add(Product) очевидна, то работа метода add(int) не ясна его пользователям. Возможно, он ищет товар в каталоге? Может быть, он выбирает n-й товар из существующей корзины и добавляет его в конец корзины? Или, возможно, он ищет заказы, ранее размещенные пользователем, и извлекает из них n-й товар? Мы просто не знаем, когда изучаем сигнатуру метода.

Чтобы понять, что делает метод add(int), нам нужно обратиться к его Javadoc-блоку, который может быть недостаточно точным. Более того, как это часто бывает, документация в Javadoc-блоке может не соответствовать коду внутри метода. Проще говоря, клиент, использующий метод add(int), неизбежно делает предположение о его внутреннем устройстве. Если клиенту повезло, 1) предположение будет верным, и 2) любые последующие изменения метода не недопустимы это предположение.

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

Я считаю, что лучшей альтернативой будет следующее:

Конструктор ProductInCatalog не является безопасным с точки зрения кода, каким он должен быть, однако это не так важно для нашего текущего обсуждения. Класс ProductInCatalog служит абстракцией Product, найденной в каталоге. Этот класс используется клиентом класса Cart. Клиент, полностью осознавая и с явным намерением, преобразует 42 (идентификатор продукта) в экземпляр ProductInCatalog. Этот дизайн больше не скрывает никаких элементов. Необходимо делать предположения и нет условий, которые код должен выполнять.

Сохраняются ли преимущества, предоставляемые перегрузкой методов? Действительно, да. Нет дублирования кода, и сложность кода уменьшается. Кроме того, читаемость кода при использовании Cart значительно улучшается. В итоге, я рекомендую избегать перегрузки методов, даже если это, несомненно, приведет к большему количеству классов в кодовой базе. Однако это уже совсем другое обсуждение.

Translated by ChatGPT gpt-3.5-turbo/42 on 2023-11-28 at 15:47

sixnines availability badge   GitHub stars