Z mojej (co prawda ograniczonej) ekspozycji na funkcjonalne języki programowania, takie jak Clojure, wydaje się, że enkapsulacja danych ma mniej istotną rolę. Zwykle różne typy rodzime, takie jak mapy lub zestawy, są preferowaną walutą reprezentowania danych nad obiektami. Ponadto dane te są zasadniczo niezmienne.
Oto na przykład jeden z bardziej znanych cytatów ze sławy Richa Hickeya z Clojure w wywiadzie na ten temat :
Fogus: Zgodnie z tym pomysłem - niektórzy ludzie są zaskoczeni faktem, że Clojure nie angażuje się w enkapsulację ukrywania danych na swoich typach. Dlaczego zdecydowałeś się zrezygnować z ukrywania danych?
Hickey: Wyjaśnijmy, że Clojure zdecydowanie kładzie nacisk na programowanie na abstrakcje. W pewnym momencie ktoś będzie musiał mieć dostęp do danych. A jeśli masz pojęcie „prywatny”, potrzebujesz odpowiednich pojęć przywileju i zaufania. A to dodaje całej tony złożoności i małej wartości, stwarza sztywność w systemie i często zmusza rzeczy do życia w miejscach, w których nie powinny. Jest to dodatek do innych strat, które występują, gdy proste informacje są wprowadzane do klas. W zakresie, w jakim dane są niezmienne, istnieje niewiele szkód, które mogą wyniknąć z zapewnienia dostępu, poza tym, że ktoś może polegać na czymś, co może się zmienić. No dobrze, ludzie robią to przez cały czas w prawdziwym życiu, a kiedy wszystko się zmienia, dostosowują się. A jeśli są racjonalni, wiedzą, kiedy podejmują decyzję na podstawie czegoś, co może się zmienić, co w przyszłości mogą wymagać dostosowania. Jest to więc decyzja dotycząca zarządzania ryzykiem, którą moim zdaniem programiści powinni mieć swobodę. Jeśli ludzie nie mają wrażliwości, aby chcieć programować abstrakcje i nieufnie podchodzić do szczegółów implementacji, to nigdy nie będą dobrymi programistami.
Pochodzący ze świata OO wydaje się, że komplikuje to niektóre z ugruntowanych zasad, których nauczyłem się przez lata. Należą do nich Ukrywanie informacji, prawo Demeter i zasada jednolitego dostępu, by wymienić tylko kilka. Powszechnym wątkiem jest to, że enkapsulacja pozwala nam zdefiniować interfejs API, aby inni wiedzieli, co powinni, a czego nie powinni dotykać. Zasadniczo, tworzenie kontraktu, który pozwala opiekunowi jakiegoś kodu na swobodne wprowadzanie zmian i refaktoryzacji bez obawy o to, jak może wprowadzić błędy w kodzie konsumenta (zasada Otwarta / Zamknięta). Zapewnia również czysty, wyrafinowany interfejs dla innych programistów, aby wiedzieć, jakich narzędzi mogą użyć, aby uzyskać dane lub je wykorzystać.
Gdy dostęp do danych jest możliwy bezpośrednio, umowa API zostaje zerwana i wydaje się, że wszystkie zalety enkapsulacji znikają. Również dane ściśle niezmienne sprawiają, że przekazywanie struktur specyficznych dla domeny (obiektów, struktur, rekordów) jest znacznie mniej przydatne w sensie reprezentowania stanu i zestawu działań, które można wykonać w tym stanie.
W jaki sposób funkcjonalne bazy kodu rozwiązują te problemy, które wydają się pojawiać, gdy rozmiar bazy kodu rośnie, tak że należy zdefiniować interfejsy API i wielu programistów jest zaangażowanych w pracę z określonymi częściami systemu? Czy są dostępne przykłady tej sytuacji, które pokazują, jak to jest obsługiwane w tego rodzaju bazach kodów?
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.
Nie całkiem. Jedyną zmianą jest to, że zmiany kończą się na nowym obiekcie. To ogromna wygrana, jeśli chodzi o rozumowanie na temat kodu; przekazywanie zmiennych obiektów oznacza konieczność śledzenia, kto może je mutować, problem ten rośnie wraz z rozmiarem kodu.