Regarding JavaBeans and the like, more often than not I've found that when getters and setters do not reference fields directly, they are contributing to a composition: as an adapter, a facade, or whatever- you-please. It is not quite as often that getters simply return a calculation based on data in their own object. With that in mind, note that such compositions usually address the problems of structuring a program in some new way, often at run time. Functional programming has lots of its own solutions for such problems.
Just for reflection: What would you do with an existing class which had a getName() method, when you suddenly realized you wanted getFirstName() and getLastName() instead? Or the reverse? What would you do if the problem you described applied to a database table? What would you do if you wanted to process several unrelated classes in a generic manner, reading data from all of them? How about an arbitrary number of existing, unrelated classes discovered at runtime? Clojure does encourage programming to interfaces (and protocols), and how much state you expose is up to you. Consider balancing this risk by including (for defrecords) a library of functions which achieve your client code's most common needs regarding a record type or a set of related types (you could probably describe this as an application of the Pareto principle). Try not to pepper such a library with getter functions without good reason though. The problem you pose is a real risk when data can be directly accessed, there is no avoiding that; every programming language has its trade-offs, just as every design pattern does. Here are a few of what I've found to be the most useful pieces of information for appreciating Clojure's functional style, coming from OO. The first two, at least, you've probably found already. ;) Directly related to your question, a clojure.org page that discusses the disadvantages of information hiding: http://clojure.org/datatypes "Object Orientation is overrated": http://clojure.org/rationale Stuart Halloway's Protocols and OO presentation (ClojureProtocolsJAOO.pdf), available from http://github.com/stuarthalloway/clojure-presentations/downloads Out of the Tar Pit, a 60 page essay on "functional/relational programming". Not a light read, but convincing. - http://web.mac.com/ben_moseley/frp/frp.html Ryan On Jun 15, 2:41 pm, Colin Yates <colin.ya...@gmail.com> wrote: > Newbie so go gentle please :). > > I am an experienced OO Java developer (decade +) considering jumping fence > to a functional language, and clojure is pretty high up on the list for a > number of reasons. > > I am so used to defining everything as objects which are sealed units of > state and behaviour that I am struggling to see how to solve the same > problem with clojure. I desperately wish somebody would write a "domain > driven design with clojure" :). > > In brief, in OO state is exposed via a well defined API. That state may be > simple properties (values) or it may be calculations (functions). And > critically, the decision as to whether it is a value or a function is an > implementation concern. The Java Bean spec defines accessors for properties > of a class, behind which lies the logic of how to retrieve that state. So, > the very common Person class will expose get/setName(), get/setAge() etc. > and as a consumer I have no idea how the results are calcualted. > > In Clojure, if I understand correctly, the preferred way would be to use a > map (or defstruct) with keys such as :name and :age. These are then > retrieved as (person :name) and (person: age) etc. > > My question is if I suddenly decided that one of those values is best > implemented as a calculation, how can I seamlessly implement that. By > seamless I mean implement it without updating any consumers of a person? > For example, if I changed the age property to be the result of a function, > I could either replace the value of age with a function that calculates age > or write a function(person)->age. > > Both of those are disruptive to the consumers of person. > > I understand that clojure is about explicitly distinguishing between state > and functions, but I see this as a high price to pay. Have I missed > something? The OO in me is saying "well, never introspect a map directly, > rather provide get-X(person) functions" but that is very very noisy. > > That's enough for now - this is, I expect, the first of many cries for help > :) > > Thanks in advance to all who reply! -- You received this message because you are subscribed to the Google Groups "Clojure" group. To post to this group, send email to clojure@googlegroups.com Note that posts from new members are moderated - please be patient with your first post. To unsubscribe from this group, send email to clojure+unsubscr...@googlegroups.com For more options, visit this group at http://groups.google.com/group/clojure?hl=en