9 ms·
I've been watching some talks online recently by Rich Hickey of Clojure fame, and he's a very interesting and convincing speaker. He basically makes the same ar
by nessus42 14y ago
I've been watching some talks online recently by Rich Hickey of Clojure fame, and he's a very interesting and convincing speaker. He basically makes the same argument that Armstrong makes here.
I'm not clear, however, how the pro-FP, anti-OO crowd address the Law of Demeter, which is often summarized as "One dot: good. Two dots: bad." The canonical example where the Law of Demeter serves us well comes from some of the original Demeter papers, which I actually read a long time ago when they were current. This canonical example is that of an object to represent a book.
One of the initial selling points of OO was that if you encapsulate the representation of an object from its interface, this ends up giving you a lot more flexibility. For the case of representing a book, pre-Demeter, a typical OO organization would have been to provide a method to give you chapters of the book as Chapter objects, and from there you could get Section objects, from which you could get Paragraph objects, from which you could get Sentence objects, from which you could extract the words as strings.
The Demeter proponents correctly argued that this OO organization of the Book rather defeats the goal of encapsulation, since with this organization you cannot restructure the internals of the Book object without breaking the API. E.g., if you decide to insert Subsections between Sections and Paragraphs, your API for extracting all the sentences of a book will change, and consequently, much of the client code will have to change.
The Demeter folks argued that instead of having to explicitly navigate to sentences, you should just be able to call a method on the Book object directly to get all the sentences. Without special tools, however, this is hard for the implementers of Book, since now they have to write tons of little delegation methods. I take it that people who are serious about following the Law of Demeter do do this, however. In the original Demeter system, Demeter would do this automatically for you. The problem with the original Demeter system is that few people actually ever used it, and it was rather complicated for Demeter to provide this automatic navigation.
So, back to FP: Rich Hickey argues to forgo damned objects and to just let the data be data. So if I follow Hickey's advice, how am I supposed to represent a book? As a vector of vectors of vectors of vectors of strings? If so, then how do I prevent a change in the representation of the Book from breaking client code? If I had followed the Law of Demeter with OO, then everything would be golden.
Sure, with this naive FP approach, I could also provide a zillion functions to fetch different sub-structures out of the book. E.g., I could have a function to return all the sections in a specified chapter, and another to return all of the sentences in the book. This, however, would end up being little different from the OO approach following the Law of Demeter, with the further downside that if you change the representation of the book, you don't know that you haven't broken the client code, because you have no guarantee that the client code isn't accessing the representation directly.
Please advise.
- acomar 14y agoThe standard lisp approach is to define your API first, and write code the meets the API. You define your API in a manner that makes the solution to the problem you're trying to solve obvious. So behind this API, you can change your data representation however you please -- just don't break the API. As for your specific question, which representation of a book is the simplest solution? That's the one you should be using. Hickey's talk on simplicity really does a good job of explaining this point.
- jonwingfield 14y agoWould an API be defined as "A set of functions that define the available operations common to that set?" If so, would those functions then delegate to progressively more concrete functions that work against data structures to perform their duties? I suppose it's obvious where I'm going here. I don't see how this is any different from just saying the word "Object." Don't get me wrong, I'm not trying to come off too sarcastic here. I'm actually quite interested in challenging the OO norm that is obviously too easily accepted right now.
- pacala 14y agoEach Module defines an api that talks about N different ValueTypes. Saying the word Object limits the api to expose exactly one ValueType.
- nessus42 14y agoRich Hickey specifically says that his approach makes you more readily adaptable to future requirement changes, rather than less adaptable, as an OO die-hard might claim. I'm not sure I understand how the "get it right to begin with" approach fits into the adaptabile-to-future-requirement-changes promise. I see how following OO, as long as you also follow the Law of Demeter, could live up to its promise of helping you adapt to future requirement changes. It has that unfortunate cost, however of requiring you to sometimes write a zillion little delegation methods upfront, which could be quite a combinatorial chore if you don't have the Demeter system automating this for you. Also, I'm pretty sure from listening to a number of Rich Hickey's talks, that he is saying very specifically NOT to hide your data behind an API. Encapsulating the data behind an API would just be the same as the OO approach for all intents and purposes. Hickey is saying to let the data be data. I.e., just data.