У меня была небольшая дискуссия с коллегой. Проще говоря, есть ли хорошая причина скрывать / инкапсулировать чистые функции?
Под «чистым» я подразумеваю определение википедии :
- Всегда возвращает одинаковые результаты из одного и того же ввода. (Ради этого обсуждения
Foo Create(){ return new Foo(); }
считается нечистым, еслиFoo
не имеет семантики значения.) - Не использует изменяемое состояние (кроме локальных переменных) или ввод / вывод.
- Не вызывает побочных эффектов.
design
pure-function
Telastyn
источник
источник
Ответы:
Чистая функция все еще может быть деталью реализации. Хотя функция не может причинить вреда (с точки зрения не нарушения важных инвариантов / контрактов), разоблачая ее, автор и пользователи этого класса / модуля / пакета проигрывают. Автор проигрывает, потому что теперь он не может удалить его, даже если реализация изменится и функция больше не будет ему полезна. Пользователи проигрывают, потому что им приходится просеивать и игнорировать дополнительные функции, которые не имеют отношения к использованию API, чтобы понять его.
источник
Вопрос задом наперед.
Вы не ищите причину сделать функцию непубличной. Это неправильное мышление для начала (на мой взгляд). Рассуждения должны идти другим путем.
Другими словами - не спрашивайте «зачем мне делать это приватным?». Спросите: «зачем мне это делать публичным?»
Если есть сомнения, не подвергайте это. Это похоже на бритву Оккама - не умножайте права сверх необходимости.
РЕДАКТИРОВАТЬ: Обращаясь к контраргументам, выдвинутым @Telastyn в комментариях (чтобы избежать расширенного обсуждения там):
Да, иногда бывает больно, если класс открыт для наследования, но вы не можете переопределить некоторые частные методы (поведение которых вы хотите изменить).
Но
protected
было бы достаточно - и это все еще не публично.Если это становится проблематичным, то просто сделайте это публичным! Есть необходимость, о которой я говорил :)
Я хочу сказать, что вы не должны делать это на всякий случай (YAGNI и все).
Обратите внимание, что сделать приватную функцию общедоступной всегда проще, чем вернуть ее обратно в частную жизнь. Последнее, вероятно, нарушит существующий код.
источник
Я не думаю, что решение скрыть / инкапсулировать функцию должно зависеть от ее чистоты. Тот факт, что функция является чистой, не означает, что внешние должны знать об этом. Интересно, что если функция чистая и предназначена для публичного использования, то ей вообще не нужно быть экземпляром интерфейса, может быть, она лучше подходит как статическая. Но опять же, все это зависит от цели договора и в данном случае от логической группировки функциональности, а не от чистоты функции.
источник
Классы должны придерживаться принципа единой ответственности . В то время как классу может потребоваться использовать другие функциональные возможности для достижения своих целей, он должен раскрывать только те функции, которые являются частью его единственной ответственности.
Вот только один пример случая, когда видимость может вызвать проблемы.
Рассмотрим класс, который фробницирует виджеты. Возможно, как часть его кода frobnication ему нужна некоторая служебная функция, которая анализирует строку: возможно, ему нужно преобразовать имя виджета таким образом, который не поддерживаются стандартными строковыми функциями.
Поскольку это чистая функция (строка входит, каким-то образом ее преобразовывает, возвращает новую строку), она может быть публичной или частной без последствий. Или это может?
Если вы сделаете это общедоступным, теперь у вашего класса есть две обязанности: изменение виджетов и преобразование строк. Это нарушает SRP и может вызвать проблемы, если другие классы полагаются на функцию. Поскольку вы думаете, что это используется только внутри класса, возможно, вы измените его интерфейс или видимость. Теперь классы в других частях системы не работают.
Сохраняя функцию приватной, никто никогда не сможет полагаться на код, который не является частью единственной ответственности класса.
источник
StringTransformer
класс для инкапсуляции двух или трех строк кода, которые используются только в одном месте? Я согласен с тем, что если код используется в нескольких местах, лучше всего разделить его на новый класс с одной ответственностью, но есть компромисс.