Из моего (по общему признанию ограниченного) знакомства с функциональными языками программирования, такими как Clojure, кажется, что инкапсуляция данных играет менее важную роль. Обычно различные нативные типы, такие как карты или наборы, являются предпочтительной валютой представления данных поверх объектов. Кроме того, эти данные обычно неизменны.
Например, вот одна из самых известных цитат из Rich Hickey из Clojure, в интервью по этому вопросу :
Fogus: Следуя этой идее, некоторые люди удивляются тому факту, что Clojure не занимается скрытием данных в своих типах. Почему вы решили отказаться от сокрытия данных?
Хикки: Давайте проясним, что Clojure сильно подчеркивает программирование на абстракции. Однако в какой-то момент кому-то понадобится доступ к данным. И если у вас есть понятие «частный», вам нужны соответствующие понятия о привилегиях и доверии. И это добавляет целую тонну сложности и небольшой ценности, создает жесткость в системе и часто заставляет вещи жить там, где им не следует. Это в дополнение к другой потере, которая происходит, когда простая информация помещается в классы. В той степени, в которой данные являются неизменяемыми, от предоставления доступа может быть мало вреда, кроме того, что кто-то может зависеть от того, что может измениться. Ну, ладно, люди делают это все время в реальной жизни, и когда все меняется, они адаптируются. И если они рациональны, они знают, когда принимают решение, основанное на чем-то, что может измениться, и что им может понадобиться адаптироваться в будущем. Итак, это решение по управлению рисками, которое, я думаю, программисты должны иметь право принимать. Если у людей нет чувства желания программировать на абстракции и опасаться сочетать детали реализации, то они никогда не станут хорошими программистами.
Исходя из мира ОО, это, кажется, усложняет некоторые из закрепленных принципов, которым я научился за эти годы. Среди них: сокрытие информации, закон Деметры и принцип единообразного доступа. Общий поток, заключающийся в том, что инкапсуляция позволяет нам определять API, чтобы другие знали, что им следует и чего не следует касаться. По сути, создание контракта, который позволяет сопровождающему некоторого кода свободно вносить изменения и рефакторинги, не беспокоясь о том, как он может вносить ошибки в код потребителя (принцип Open / Closed). Он также предоставляет чистый, кураторский интерфейс для других программистов, чтобы узнать, какие инструменты они могут использовать для получения или создания этих данных.
Когда к данным разрешен прямой доступ, этот контракт API нарушается, и все эти преимущества инкапсуляции, похоже, исчезают. Кроме того, строго неизменные данные, по-видимому, делают передачу вокруг доменных структур (объектов, структур, записей) гораздо менее полезной в смысле представления состояния и набора действий, которые могут быть выполнены в этом состоянии.
Как функциональные кодовые базы решают эти проблемы, которые, кажется, возникают, когда размер кодовой базы становится огромным, так что необходимо определить API-интерфейсы, а многие разработчики вовлечены в работу с конкретными частями системы? Существуют ли примеры такой ситуации, демонстрирующие, как это обрабатывается в кодовых базах такого типа?
Also, strictly immutable data seems to make passing around domain-specific structures (objects, structs, records) much less useful in the sense of representing a state and the set of actions that can be performed on that state.
На самом деле, нет. Единственное, что меняется, это то, что изменения заканчиваются на новом объекте. Это огромная победа, когда дело доходит до рассуждений о коде; Передача изменяемых объектов означает необходимость отслеживать, кто может их видоизменить, и эта проблема возрастает в зависимости от размера кода.