Наличие пар статических и инстанцированных методов, выполняющих одни и те же задачи?
при разработке двумерного векторного класса как части математической библиотеки я рассматриваю возможность наличия статических пар и пар методов экземпляра по стилистическим и юзабилити причинам. То есть две эквивалентные функции, но одна статична и не мутирует, а другой приведен в Примере & мутирует. Я знаю, что я не первый человек, который рассматривает эту проблему (см. здесь, например), но я не нашел никакой информации, которая напрямую касается его.
плюсы наличия статических и пары методов экземпляра:
- некоторые люди предпочитают использовать один или другой, а в некоторых случаях возможность выбора облегчает чтение кода.
-
подразумевается, что статические методы не мутирует при статических и приведенных методов. Это может сделать вызывающий код намного яснее, например:
someVector = Vector2d.add(vec1, vec2); someVector = (new Vector2d(vec1)).add(vec2); // does the same thing although more convoluted. // similarly adding directly to a vector is simpler with a mutator method. someVector.add(vec2); someVector = Vector2d.add(someVector, vec2);
это особенно важно, когда используются длинные цепочки вызовов функций, что является общим для векторные иллюстрации.
операции на месте могут быть быстрее вычислительно, чем создание нового экземпляра для каждой операции. Пользователь решает, когда производительность важна. Для пользователей векторного класса производительность может быть важна, поскольку векторы часто используются в вычислительно дорогом коде.
плюсы наличия только статических или экземпляров методов, но не обоих:
нет значительной избыточности кода. Легче поддерживать.
меньше наворотов. В Javadoc будет почти вдвое меньше.
нет необходимости сообщать пользователям, что статические методы никогда не мутируют, а не геттерные методы всегда мутируют.
как неодобрительно относится наличие пар методов static/instance? Используется ли он в каких-либо крупных библиотеках?
широко известен ли шаблон "статические методы не мутируют, методы экземпляра"?
2 ответов
Я думаю, что ваша концепция предоставления как статических/неизменяемых, так и экземпляров/изменяемых методов является хорошей. Я думаю, что различие легко объяснить и будет легко для пользователей API понять и запомнить.
Я думаю, что ваш код реализации API не будет иметь избыточных бизнес-логики. Вы обнаружите, что вы повторяете шаблон, где статическая реализация создает новый экземпляр и вызывает метод экземпляра на этом новом экземпляре.
учитывая, что я ленивый, я бы посмотрел на создание немного инфраструктуры, которая автоматически генерировала бы статические методы, их javadoc и их модульные тесты во время компиляции. Это было бы излишним, если у вас есть 10 методов, но становится большой победой, если у вас есть 1000 методов.
в первой части "статические методы не мутируют", что широко используется в ООП. Я не слышал, чтобы это выражалось открыто. Но это здравый смысл: "если вы измените объект, почему метод может быть статическим, если он может быть методом экземпляра?"Поэтому я полностью согласен с "статическими методами не мутировать".
во второй части " методы экземпляра делают [мутировать]", это на самом деле не так широко используется. Это скорее зависит от того, решите ли вы применить свой дизайн неизменность или переменчивости. Примеры из API Java:java.lang.String
is неизменяемые, java.util.Date
is mutable (скорее всего случайно / плохой дизайн), java.lang.StringBuilder
и mutable умышленно (это его цель). переменчивости может привести к оборонительные клонирования для защиты кода от ошибок мутации. Действительно ли это проблема, зависит от нескольких вещей:
- это API для других? Вы никогда не знаете, как они будут использовать ваш код... IMO более важно защитить код API от ошибок мутации, чем обычный код.
- насколько хорошо покрытие модульного теста? Будут ли ваши модульные тесты находить все ошибки мутации,которые могут проникнуть? Если вы правильно следуете TDD (3 Закона TDD дяди Боба), и это не API-код, ошибки мутации очень маловероятны, чтобы проникнуть, не будучи мгновенно обнаружены.
- если у вас есть код, который должен защитить себя против мутационных ошибок, использующих защитное клонирование, как часто этот код называется? Если защитные клоны создаются часто, может быть лучше использовать неизменяемые объекты, чем изменяемые объекты. В основном это вызов количества вызовов методов только для чтения (которые в конечном итоге будут оборонительно клонироваться) ассоциирующих классов против количества вызовов методов мутатора на самом классе.
лично я предпочитаю неизменяемые объекты, я фанат final
(если бы я мог изменить Java, я бы final
по умолчанию для всех полей и переменных, и ввести ключевое слово var
чтобы сделать их не окончательными), и я пытаюсь сделать функциональное программирование на Java, хотя это не функциональный язык программирования, насколько это возможно. Из моего опыта я знаю, что я трачу значительно меньше времени на отладку своего кода, чем другие (на самом деле я запускаю отладчик Java, возможно, два раза в год или около того). У меня недостаточно эмпирических данных и надлежащего анализа для создания каких-либо " причинных связь " между опытом, неизменностью, функциональным программированием и корректностью, поэтому я только скажу, что считаю, что неизменность и функциональное программирование помогают правильности, и вам придется придумать свое собственное суждение об этом.
заключение во второй части "методы экземпляра делают [мутировать]" является широко используемым предположением в случае, если объект в любом случае является изменяемым, иначе методы экземпляра будут клонироваться.