aspose file tools*
The moose likes OO, Patterns, UML and Refactoring and the fly likes Humane Interfaces? Big Moose Saloon
  Search | Java FAQ | Recent Topics | Flagged Topics | Hot Topics | Zero Replies
Register / Login
JavaRanch » Java Forums » Engineering » OO, Patterns, UML and Refactoring
Bookmark "Humane Interfaces?" Watch "Humane Interfaces?" New topic
Author

Humane Interfaces?

Jeff Albertson
Ranch Hand

Joined: Sep 16, 2005
Posts: 1780
I suppose this is forum is the best fit for the following article, and its wake:

http://martinfowler.com/bliki/HumaneInterface.html

Any comments, vis-a-vis Java? I'm of two minds. I'd rather implement
a minimal interface but program to a more humane, or maximal, one.


There is no emoticon for what I am feeling!
Ilja Preuss
author
Sheriff

Joined: Jul 11, 2001
Posts: 14112
Well, as the article is about class design, I'll move it to our OO forum...


The soul is dyed the color of its thoughts. Think only on those things that are in line with your principles and can bear the light of day. The content of your character is your choice. Day by day, what you do is who you become. Your integrity is your destiny - it is the light that guides your way. - Heraclitus
Ernest Friedman-Hill
author and iconoclast
Marshal

Joined: Jul 08, 2003
Posts: 24166
    
  30

Just some rambling comments...

The whole debate makes me think about TDD (as in "Test-Directed Design") and also the Law of Demeter. Fowler mentions Java's List interface, so let's go with that.

If you're designing a List interface in isolation, you're very likely to come up with something like java.util.List. But if you're using TDD to develop the implementation and interface together, then I think the "Humane Interface" is more likely; i.e.,



Now, I've written a very simple test, and I've got to add two things to ListImpl that current JDK lists don't have: a constructor that takes an Object array (why, oh why, didn't they include these?) and the last() method that Fowler talks about in his article. So by doing TDD, I think you tend to lean toward the "Humane Interface."

The Law of Demeter suggests that it's bad to get too involved with other objects, and offers specific guidelines on avoiding entanglement. Very often, I find that Demeter violations are solved by pushing behavior into an object. Taken literally, Demeter says that iterating over a collection and doing something to each item is wrong. This is not something easy to do in Java, but in Ruby it's solved, more or less, by letting arrays and other collections have methods that accept a code block and execute it for each item in a collection. So following Demeter also leads to enlarging the interfaces of library-like classes.


[Jess in Action][AskingGoodQuestions]
Stan James
(instanceof Sidekick)
Ranch Hand

Joined: Jan 29, 2003
Posts: 8791
This is not something easy to do in Java, but in Ruby it's solved, more or less, by letting arrays and other collections have methods that accept a code block and execute it for each item in a collection.


Visitor essentially does this with some extra code in the items in the collection. Visitor was high on the "which pattern would you vote off the island" list at some convention or other. I tend to like it more than most people do, I guess. I think it saved my bacon in a third party collection that was "closed for modification" and in a dynamic tree I had to build at work where there never was a real collection.


A good question is never answered. It is not a bolt to be tightened into place but a seed to be planted and to bear more seed toward the hope of greening the landscape of the idea. John Ciardi
Ilja Preuss
author
Sheriff

Joined: Jul 11, 2001
Posts: 14112
I don't see how Visitor helps here. I understood Ernest to mean more something along the lines of code blocks - kind of "anonymous strategies". Like the forAllDo method in http://jakarta.apache.org/commons/collections/api-release/org/apache/commons/collections/CollectionUtils.html - just implemented directly on the collection instead of as a static utility method. (That's how Smalltalk does it.)
Frank Carver
Sheriff

Joined: Jan 07, 1999
Posts: 6920
My take on all this is that there is room for both approaches, even in a single language, even in a single project. I have done it in my designs several times.

As pointed out above. Designing an abstraction from scratch (and typically in isolation) often leads to a kind of "minimalist but complete" solution which might be clumsy for real world use but contains very little duplication.

Similarly, Designing from real requirements (be it TDD or any other similar approach) often leads to a friendly but internally messy and duplicated solution.

My gut feeling is usually to separate the two, but keep them both available where they are used by other code. I've heard this referred to as "refactoring", and I am fairly sure Mr Fowler has also heard the term

Sometimes the "humane" version of a class/interface directly inherits from the "minimal" version, sometimes it delegates, sometimes it's just a collection of static utility methods somewhere (java.util.Collections vs java.util.Collection, anyone?)

The whole "humane interfaces" furore seems like a storm in a teacup to me. Good practice is still the same in both cases :- build what the user needs; refactor to remove duplication; repeat.


Read about me at frankcarver.me ~ Raspberry Alpha Omega ~ Frank's Punchbarrel Blog
Stan James
(instanceof Sidekick)
Ranch Hand

Joined: Jan 29, 2003
Posts: 8791
forAllDo() is interesting. I hadn't looked at that framework. Many of the closures and transformers look like somebody set out to see "How many of these can I make up?" rather than harvesting them from places where they really paid off. I've done that before for sure, like duplicating all my favorite REXX concepts in a few other languages.

Taken literally, Demeter says that iterating over a collection and doing something to each item is wrong.


Does forAllDo() just push this (maybe) "wrong" thing into a library where you can ignore it? Maybe that's ok ... to some degree libraries let you pretend the language supports it. No matter how much we love our OO principles, it's all 1s and 0s down there somewhere.
Ilja Preuss
author
Sheriff

Joined: Jul 11, 2001
Posts: 14112
Originally posted by Stan James:
Does forAllDo() just push this (maybe) "wrong" thing into a library where you can ignore it?


The Jakarta Commons thing, yes.

The "original" Smalltalk thing, no - there it is implemented directly on the collection, so it's the collection iterating over its own items, which is fine with Demeter.

In Java, you can't add methods to an existing class without touching it's source code, and Sun didn't think about providing that method, so a utility method is the closest you can come. (To be fair, Tigers enhanced for loop comes close.)
Ilja Preuss
author
Sheriff

Joined: Jul 11, 2001
Posts: 14112
Originally posted by Frank Carver:
As pointed out above. Designing an abstraction from scratch (and typically in isolation) often leads to a kind of "minimalist but complete" solution which might be clumsy for real world use but contains very little duplication.

Similarly, Designing from real requirements (be it TDD or any other similar approach) often leads to a friendly but internally messy and duplicated solution.


I don't understand what a "humane interface" has to do with messy and duplicated solutions. Could you please elaborate? Thanks!
Frank Carver
Sheriff

Joined: Jan 07, 1999
Posts: 6920
My use of "messy" was only intended to indicate some sort of design steps or process, rather than an end result. The two sequences I mentioned were roughly:

approach 1 ("from scratch"):
  • idea, theory or model
  • minimal solution
  • add (potentially in more than one place) code which uses minimal solution
  • usable application(s)



  • approach 2 ("from experience"):
  • grab lots of bits used in similar applications
  • merge them together
  • add some "glue"
  • usable application(s)



  • The general problem with approach 1 is the potential duplication at step 3. This "fault line" between system/library software and "application" software has led to a lot of code duplication over the years, and seems to be one of the problems that a "humane" approach aims to solve.

    The general problem with approach 2 is that code is put into the codebase before it is known if it is needed or not. Depending on the origin and state of this code (some my be copy-n-paste, some may be re-implementation of a familiar pattern) this may involve duplication, or may need adapting to fit the new context. Any such "messiness" can be fixed, but the end result will still be more code than may actually be needed.

    My preferred solution is to include some of both these approaches.

    Start by building just the code that is needed at any point in time. At the start of a project that may just be a small number of "humane" methods or a concise and minimalist model. As more functionality is added to the application, there becomes more pressure for more methods.

    This is the point at which the minimalist/humane decision becomes important - my response is to follow the need for simplicity by deriving a concise, consistent and individually testable "core", but also to follow the need for suiting the calling code and removing duplication by adding an extra layer of more "friendly" but potentially less generic interfaces.

    Or am I still missing the point?
     
    I agree. Here's the link: http://aspose.com/file-tools
     
    subject: Humane Interfaces?
     
    Similar Threads
    Clean Code A Handbook of Agile Software Craftsmanship - Test POJO
    Anti-Pattern: Anemic Domain Model
    what is POJO??
    Relationship between Model (in MVC) and DAO
    Why does JUnit create a new instance of a class each time it calls a test method?