 |
Seventeenth century object design
Posted by ljnelson on September 02, 2004 at 08:10 AM | Comments (16)
Hello, first of all. It's an honor to be part of the java.net weblogging community.
A discussion concerning component
reuse brought me back to my philosophy major days in college. Who knew
British empiricism could help you with object design?
The discussion was (is) about, loosely, how best to design an object or a
component for reuse. You want to get the hypothetical object down to what's
important across domains, to trim away the fat, but, as a competing concern, to
make it rich enough that people won't have to reinvent the wheel. Slimming down
your object also provides incentive for someone else to use it, provided you
don't slim it down so far that it's impractical.
What is this "fat" we're talking about? In general, it's concerns or aspects
or facets of the real-world thing that our object is modeling. There are many
facets about a hypothetical and reusable Person object (and the set
of all persons that it models), for example, that could be included, ranging
from names to measurements to relationships with others. Which of these groups
of attributes is necessary for a Person to be a
Person? Which is superfluous? What is the Person
apart from these groups of attributes?
John Locke examined
these issues in An Essay
Concerning Human Understanding. Ruthlessly paraphrased, and butchered
somewhat for this weblog's purposes, he argues that when you hear someone
mention a person, you frame a "complication or collection" of "simple ideas" in
your mind that "go constantly together", such as height, weight, general shape,
etc. In Locke's view we humans in the normal unexamined course of our lives
don't imagine these ideas simply existing on their own, so we subconsciously
posit the existence of a "substratum" that they bind to, although strictly
speaking we never entirely know what we're talking about. Locke calls this
substratum substance, and, believe it or not, it's one way of thinking
about object reuse, whether it exists or not.
A couple of choice quotes from Locke on this whole subject:
If any one should be asked, what is the subject wherein colour or
weight inheres, he would have nothing to say, but the solid extended parts; and
if he were demanded, what is it that solidity and extension adhere in, he
would... [answer] SOMETHING, HE KNEW NOT WHAT.
...[O]ur...ideas of substances...have always the confused idea of
something to which they belong...and therefore when we speak of any sort of
substance, we say it is a thing having such or such qualities; as body is a
thing that is extended, figured, and capable of motion; spirit, a thing capable
of thinking; and so hardness, friability, and power to draw iron, we say, are
qualities to be found in a loadstone. These...intimate that the substance is
supposed always SOMETHING BESIDES the extension, figure, solidity, motion,
thinking, or other observable ideas, though we know not what it
is.
Let's apply Locke to object design and see where it leads. Suppose he's
right: a person is simply a collection of related attributes or facets that
adhere to some substratum. Let's model this explicitly.
Backing up for a second for contrast, the normal way you would design a
domain-independent Person object, assuming for the moment you
could, would be to pick some attributes that you thought were sufficiently
general and important to be included in this superclass (and here's where you
run into problems). Here, for the sake of brevity, is my silly offering:
public class Person {
// My selection for an attribute that is important enough to
// be included in this reusable class. Yours could be different.
// Of course that means we'll probably end up not reusing each other's
// classes. Hmm.
private String name;
public Person() {
super();
}
public String getName() {
return this.name;
}
public void setName(final String name) {
this.name = name;
}
// etc.
}
Of course, picking what those attributes are is what makes reusable object
design so tough.
Locke, if he were an object designer, would be a rebel. He would probably
start with the attributes--the collections of simple ideas--and graft them on to
some simple "substance" object that would be deliberately designed to be more or
less inscrutable. As it turns out, this is a much better way to achieve object
reuse across domains. Maybe an extreme version of his code would look something
like this:
public interface IKnowNotWhat {
// If only we knew what it was!
}
public class Person implements IKnowNotWhat {
public Person() {
super();
}
}
public abstract class CollectionOfSimpleIdeas {
protected final IKnowNotWhat substance;
public CollectionOfSimpleIdeas(final IKnowNotWhat substance) {
super();
this.substance = substance;
if (substance == null) {
throw new BritishEmpiricismMisunderstoodException();
}
}
public IKnowNotWhat getSubstance() {
return substance;
}
}
public class PersonNames extends CollectionOfSimpleIdeas {
private String familiarName;
public PersonNames(final IKnowNotWhat substance) {
super(substance);
}
public String getFamiliarName() {
return this.familiarName;
}
public void setFamiliarName(final String familiarName) {
this.familiarName = familiarName;
}
// etc.
}
public class PersonMeasurements extends CollectionOfSimpleIdeas {
private int heightInInches;
public PersonMeasurements(final IKnowNotWhat substance) {
super(substance);
}
public int getHeight() {
return this.heightInInches;
}
public void setHeight(final int height) {
this.heightInInches = height;
}
// etc.
}
The key insight here is that people aren't interested in a reusable
Person object at all. They are interested in different
combinations of facets that all concern a person in a particular domain.
A financial services programmer doesn't care about a person's weight, but that
might be very important to the programmer of an insurance system. Explicitly
modeling a person this way--inside out--lets each domain of attributes stand
alone, but also lets them play nicely together when bound together. What's
important is that the attributes are reused, not the substratum.
All of this philosophy has made my brain hurt. I'm going to go get some
lunch (although I know not what).
Bookmark blog post: del.icio.us Digg DZone Furl Reddit
Comments
Comments are listed in date ascending order (oldest first) | Post Comment
-
Easy to use little things?
Hi Laird,
Have you tried facet-based code like this? How'd it go?
Do you think this is a case of small things being easier to reuse than big things? (But harder to find, track and market...)
Or is it something deeper -- Class hierarchies not really matching the problems we hit for data representation?
Dave
protected Chef[] expandEmpire()
{
try
{
SomePlace somePlace = pickSomePlace();
somePlace.mispronounceName();
colonize(somePlace);
excerciseConflictingIdeals();
}
catch(BritishEmpiricismMisunderstoodException beme)
{
//todo Should we abandon the ideals of the empire, or give up on it.
//Wow, this empty catch block has been here a long time. Has anyone called this code since 1948?
}
finally
{
Chef[] expatChefs = temptGoodCooks(londonRestaurantScene);
return expatChefs;
}
}
Posted by: dwalend on September 02, 2004 at 07:53 PM
-
Empiricism is not imperialism
Just a small point, I don't think the author was talking about British colonisation of the world, but a particular type of gaining knowledge through experimentation.
Posted by: ricky_clarkson on September 03, 2004 at 06:57 AM
-
Easy to use little things?
I've used this on a couple of projects now. It actually isn't that different
from "regular" OO programming, with the exception that the "substance" is passed
in to your object instead of created by it.
Where things get even more metaphysically interesting is when you start
thinking about the computer equivalent of taking up time and space. That is,
there are many things that are attached to David Walend, but many, if not all,
of those things can change. What doesn't change is that David Walend is at a
particular point in space at a particular time (objections about death, living
on in memory, fictional characters etc. cheerfully ignored). The computer
analog of this is something like an ID in a database, or an address in memory.
That's the "I know not what" that you pass in in this style of programming;
that's the substratum to which attributes adhere.
The difficulty, as you quite rightly point out, is that your facets become
hard to manage because there are a lot of them. I've found, though, that on a
given project, in that project's name- or package-space, there aren't
that many. And this kind of programming (facet-oriented programming?) is
a good way to start migrating duplicated code from, say, two separate
departments in a big company into a common repository. Turn each department's
Person object into something named a bit more facet-like, and
modify their constructors to take in something that those facets are
going to bind to. Now migrate the common stuff that they share up to a common
facet superclass, or, perhaps, to a common facet that also contains the same
substratum. You haven't really changed anyone's code, but you've altered
the underpinnings it's based on so that the whole shooting match is a bit more
centralized.
Incidentally, this is the same principle that RDF is founded on. For example, here's a bit
of RDF taken from the primer:
August 16, 1999
Note that the description (a facet) is "about" a substratum (in this case,
whatever the thing is--I know not what--that is pointed to by the url
http://www.example.org/index.html).
Posted by: ljnelson on September 03, 2004 at 07:29 AM
-
Reusing objects
So, what you say is : one must define first if you want a new kind of object-person which has new attributes or if you want just to handle in a different way the attributes already defined for the already existent object-person.
Right?
Posted by: yuriha on September 03, 2004 at 11:21 AM
-
Mixins
It sounds like you want mixins.
Ruby anyone? :-)
Posted by: scott_sauyet on September 03, 2004 at 12:39 PM
-
Reusing objects
Well, more like this: don't worry about the definition of Person so much, becuase no one will be able to agree what should be in it. Worry instead about the definition of PersonNames (or whatever you want to call it), PersonMeasurements, PersonRelationships, PersonBankAccountInformation, etc.
Posted by: ljnelson on September 04, 2004 at 09:54 AM
-
Mixins
No, not really, because in such a case my Person object would still have to inherit from/include any facet mixins I might define. If you do it "backwards" instead, and have the facet pull in the Person, then you don't need mixins at all.
(The tricky problem is, as Dave points out below, if you're armed with, say, a PersonMeasurements object that attaches to a particular Person substrate, how do you figure out what other facets that Person is associated with? This is not insoluble, just tricky.)
Posted by: ljnelson on September 07, 2004 at 08:40 AM
-
Easy to use little things?
This blog entry sounded intriguing in the beginning but I was lost completely when I started reading about the substrates, substances and metaphysics. What is the author trying to do and what is its relation to reuse here?
I find this "talking in abstract sense" thing just as amusing as the nexy guy. Even I used to do the same during my initial days of experimentation with the idea that "OO is natural to humans." Once, after a full night of discussion with friends and coworkers, I even gave some enlightening statements such as "A pen is a pen with or without a cap."
The statement was just an "enlightening thing." That's what it is. Nothing more nothing less. These sort of discussions only caused slippage of schedules and running projects over budgets or only to find ourselves coding a piece of very badly designed object models.
I STILL see so many people talk in that "abstract" sense in a serious design session as well. The way I see this type of talk/literature is that it is the inefficiency of not being able to relate things in the problem domain or solution domain on hand or in the real software development world. Software Engineering in the enterprise has matured enough and no longer qualifies for an art form.
So, anyways, after spending about 30 minutes on this entry, I am neither able to understand the problem that the author is taking about nor the solution he is suggesting.
In Java or any OO language please....
Anyone?
Posted by: javampire on September 14, 2004 at 05:16 PM
-
Easy to use little things?
First of all, my apologies for failing you. Obviously I was not as clear as
I should have been. Thanks for the feedback.
In an effort to be more clear, let's start with your "A pen is a pen with or
without a cap" statement, which is enlightening. Let's follow where that
leads.
Suppose you have as your goal to design a Pen object that will
be used by hundreds of companies worldwide. So let's say you do something like
this:
public class Pen {
public void write(final String message) {
//...
}
public Cap getCap() {
//...
}
public float getInkCapacity() {
}
public boolean hasShirtClip() {
}
public Color getInkColor() {
}
public float getInkRemaining() {
}
public boolean isDisposable() {
}
}
(This, in case you can't tell, is a very contrived example, but roll with me for
a bit.) So I come along, looking for an already-built Pen object I
can use. I see this one, which seems to have rather a lot of methods on it.
"Gee," I think, "this feels a little heavyweight. I wish it were pared down so
it better plugs in to my problem." So I call you up, and we agree that maybe we
can remove some of the properties of your Pen object to make it
feel less heavyweight, and make it less tied to the domain of Pens That Have
Shirt Clips and Ink, and more generic (and hence more usable across
domains).
First, we remove the getCap() method, because a pen is a pen
without a cap. Then we remove the ink methods, because not all pens have ink
(feather pens come to mind, as do calligraphy nibs). Finally, exposing some
features on the Pen object as booleans is a little overkill,
because where do you stop (should you add methods like
isMadeInFrance()? So why encode disposability as a
boolean)?
So now we're left with this:
public class Pen {
public void write(final String message) {
//...
}
}
"Great," I think, "now I have my reusable Pen object. I'll just
subclass it and add in the collections of attributes that I need. As it turns
out, hmm, I actually do need ink-related attribtues [let's say] so I'll
just subclass the thing." So I do this:
public class InkContainingPen extends Pen {
public Color getInkColor() {
//...
}
public float getInkRemaining() {
//...
}
public float getInkCapacity() {
//...
}
}
Now I decide that my domain requires that Pen objects in it need to
be able to answer questions about their price. So...hmm. So I do some more
subclassing, beginning to get that bad feeling like maybe composition somehow is
a better approach, but not yet doing anything about it:
public class PrestigiousPen extends InkContainingPen {
public Money getPrice() {
//...
}
// And no prestigious pen is capless...so we'll just throw that in here
// too. Hmm. This is getting messy.
public Cap getCap() {
//...
}
}
Now that I've created this mess, I step back and pause for a minute, because I
know I've done something bad. I decide to spend some time thinking abstractly,
as ill-advised as that may be. :-) What I recognize is that really
the only "necessary" property of a pen is that it is able to write. And, now
that I have destroyed my own self confidence by creating this evil inheritance
hierarchy, maybe I'm not even so sure about that. Gee, figuring out what
properties are necessary for a pen to be a pen turns out to be kind of
difficult.
Now I've really done it. Now I don't know what I know any more.
Abstract thought sure does get you into some nasty situations! Well, one thing
I do know is that the ink-related methods seem to go together in some
sort of fundamental way. They are kind of a collection of related properties,
if you will. And the money related methods (OK, there's only one in this
ridiculous example; pretend there are many) go together as well. Another
collection of attributes.
Hey, what if a pen in any given domain is simply a collection of these
collections of attributes, and nothing else? Hey, then I could use composition
instead of inheritance, and as my poor, feeble brain comes up with new
attributes that Just Have to Belong to a Pen I can graft them on after the fact
instead of having to refactor, or rejigger inheritance hierarchies.
So I do something like this instead:
public class InkFacet {
public InkFacet(final Pen pen) {
super();
//...
}
public Pen getPen() {
//...
}
public Color getInkColor() {
//...
}
public float getInkRemaining() {
//...
}
public float getInkCapacity() {
//...
}
}
...and this:
public class PrestigeFacet {
public PrestigeFacet(final Pen pen) {
super();
//...
}
public Pen getPen() {
//...
}
public Money getPrice() {
//...
}
}
public class CapFacet {
public CapFacet(final Pen pen) {
super();
//...
}
public Pen getPen() {
//...
}
public Cap getCap() {
//...
}
}
Now whatever you do to your Pen object I don't care about because I
can just graft on my facets as I need them.
Actually, I come to realize, these facets don't have anything to do with pens
at all, necessarily. They're just collections of attributes, after all, and
they could be part of the total description of any sort of object. So:
public class PrestigeFacet {
public PrestigeFacet(final Object substrate) {
super();
//...
}
public Object getTheThingThisCollectionOfAttributesIsAbout() {
//...
}
}
...or, perhaps a little more concisely:
public class PrestigeFacet {
public PrestigeFacet(final Object substrate) {
super();
//...
}
public Object getSubstrate() {
// replaces the getTheThingThisCollection... method
}
}
Now I realize that these facets actually have nothing intrinsically to do with
my domain at all. That is, they aren't trade secrets, they don't necessarily
describe pens (the InkFacet could describe bottles of ink, or a
warehouse that sells boxes of ink, or a printer. A CapFacet could
describe a baseball player. So why are they in my codebase, and not
yours (where "you" are the Place Where Reusable Software Comes From)? So I call
you up and I say, hey, I have these collections of attributes that can describe
lots of things. How about putting them in your codebase? And you do, and my
code now becomes much more about reusing your stuff than it is about my
stuff.
The fun (for me, anyway) part of this insight is realizing how much in common
it has with philosophy and metaphysics. Hence the John Locke reference; I loved
the fact that this brilliant man was reduced to calling
the-thing-that-attributes-stick-to an "I Know Not What". Java would call that
an Object. What do they have in common? If you read more of
Locke, he will tell you that substrates--the things attributes stick to that you
can't describe--are basically all characterized by taking up space at a
particular set of moments in time. That, of course, is exactly what an
Object does as well.
Posted by: ljnelson on September 15, 2004 at 09:44 AM
-
I Know Not What?
ljnelson, No apologies, Sir. Rather I should apologize because my words were
a little bit harsh as they came out of frustration to understand the gist
of this article. No hard feelings. And by the way, nice touch with the "Pen"
:-)
Back to the "facets" now. Facets are needed when we need to modify or
control the behavior of an object. Facets always expose a "subset" of
the actual object (to continue speaking "abstractly" lets refer to this as
IKnowNotWhatObject). The fundamental rule of Facets is that they are
independent on their own. Meaning, they don't know anything about the actual
object. So, the meaning of IKnowNotWhatObject basically from the Facet's
perspective - a facet does not know and does not care what object has this
facet.
Applying facets to achieve "composition" in the unnatural way seems to be
pretty much like an antipattern. I disagree with the implementation
choice of passing the IKnowNotWhatObject to the Facet's constructor. That
it goes against the nature's way which is a Pen has Ink, Cap etc. The
examples above reflect the exact opposite -- the cap has a Pen! So a pen MUST
know about what facets it has. Otherwise it is not usable in the first place.
Facets employ the principle of least authority via interface oriented
programming to promote the "capability" oriented frameworks. So they are found
in implementations of aspects like security, persistence, auditing etc. It is
unfortunate that we don't come across them not as frequently as we should.
Also from my personal experience that data representation centric
reuseability is much less frequent and doesn't add much value when compared
to reusing the behavior. More over it adds more than many layers to access
the data and results in IKnowNotWhat style code.
OO Father, forgive them for they know not what they do
For, disregarding what is "I Know Not What", loving meaningless composition
instead of you.
So, facets need to be like this.
public interface Facet1{ void foo();}
public interface Facet1{ void bar(Blah blah);}
public interface Facet1{ Yada fubar();}
public interface ActualInterface extends Facet1, Facet2, Facet3 { Something someFunctionalityOfItsOwn();}
Posted by: javampire on September 16, 2004 at 09:19 PM
-
Easy to use little things?
ljnelson, No apologies, Sir. Rather I should apologize
because my words were a little bit harsh as they came out
of frustration to understand the gist of this article. No
hard feelings. And by the way, nice touch with the "Pen"
:-)
Back to the "facets" now. Facets are needed when we need
to modify or control the behavior of an object. Facets
always expose a "subset" of the actual object (to continue
speaking "abstractly" lets refer to this as
IKnowNotWhatObject). The fundamental rule of Facets is that
they are independent on their own. Meaning, they don't know
anything about the actual object. So, the meaning of
IKnowNotWhatObject basically from the Facet's perspective -
a facet does not know and does not care what object has
this facet.
Applying facets to achieve "composition" in the
unnatural way seems to be pretty much like an antipattern.
I disagree with the implementation choice of passing the
IKnowNotWhatObject to the Facet's constructor. That it goes
against the nature's way which is a Pen has Ink, Cap etc.
The examples above reflect the exact opposite -- the cap
has a Pen! So a pen MUST know about what facets it has.
Otherwise it is not usable in the first place. Facets
employ the principle of least authority via interface
oriented programming to promote the "capability" oriented
frameworks. So they are found in implementations of aspects
like security, persistence, auditing etc. It is unfortunate
that we don't come across them not as frequently as we
should. Also from my personal experience that data
representation centric reuseability is much less frequent
and doesn't add much value when compared to reusing the
behavior. More over it adds more than many layers to access
the data and results in IKnowNotWhat style code.
OO Father, forgive them for they know not what
they do
For, disregarding what is "I Know Not What", loving
meaningless composition instead of you.
So, facets need to be implemented like this:
public interface Facet1{ void foo();}
public interface Facet2{ void bar(Blah blah);}
public interface Facet3{ Yada fubar();}
public interface ActualInterface extends Facet1, Facet2, Facet3 { Something someFunctionalityOfItsOwn();}
Posted by: javampire on September 16, 2004 at 09:32 PM
-
:-D
that's a very interesting idea! i think i'm starting to get some picture of how to make use of that. Still need some more time to make it clear, though. Thanks anyway :-D a very nice way of viewing object and managing its attributes to improve code reusing.
Posted by: maowmaow on September 19, 2004 at 11:10 AM
-
Easy to use little things?
I'm going to gently disagree with you on several counts.
You write:
The fundamental rule of Facets is that they are independent on their
own. Meaning, they don't know anything about the actual object.
That isn't really the fundamental rule. The fundamental rule is more like this:
a particular facet is simply those attributes that your application needs to
work with; no more and no fewer.
Next, you write:
I disagree with the implementation choice of passing the
IKnowNotWhatObject to the Facet's constructor. That it goes against
the nature's way which is a Pen has Ink, Cap etc. The examples above reflect the
exact opposite -- the cap has a Pen! So a pen MUST know about what facets it
has. Otherwise it is not usable in the first place.
Why does a Pen need to know what its facets are? If your
application is all about Caps, then write your application in terms
of Caps. If you need to instantiate a, say,
Measurements facet, just construct one, and pass the (more or less
opaque) Pen object to its constructor.
Next, you write:
Facets employ the principle of least authority via interface
oriented programming to promote the "capability" oriented frameworks. So they
are found in implementations of aspects like security, persistence, auditing
etc. So, facets need to be implemented like this:
public interface Facet1{ void foo();}
public interface Facet2{ void bar(Blah blah);}
public interface Facet3{ Yada fubar();}
public interface ActualInterface
extends Facet1, Facet2, Facet3 {
Something someFunctionalityOfItsOwn();}
I'm not sure what you mean, but facets as I have loosely backed into defining
them are simply collections of attributes that are usable in a given domain by a
given application. If you want to make them interfaces, you certainly can. But
you are not obligated to.
Posted by: ljnelson on September 20, 2004 at 08:11 AM
-
Easy to use little things?
You are correct. Facet's fundamental rule is: a
particular facet is simply those attributes that your
application needs to work with; no more and no fewer.
And therefore, a Facet doesn't really care about which
object has that facet. As the user of facet, an application
object, is only interested what the functionality of facet
is about.
Here are couple of lines that may make my point clear.
The very fact that you are passing the
IKnowNotWhatObject to the facet constructor, makes the facet
*aware* of it. And if the application is all about Caps
then we don't have to think about an object called Pen.
That is what makes this "abstract" talk a big no-no in
general application design discussions as it completely
ignores the problem-on-hand. Take the example for instance,
we started with "Pen" and now we say we don't have to work
with pen.Don't get me wrong, you probably are talking about
another application that only deals with Caps. But that
application is something that probably *uses* a Cap (or a
Facet) and doesn't really care about how it is
constructed.
If we are really planning to make the *data representation*
generic, we could program with an object that has only
a java.util.Map and not worry about Facets either? But, doing so is not prudent.
So, I just put a couple of templates to make it more reusable. But,
the real question is what value these *reusable* objects bring
to an application? Now, one may say, it is a pattern and we cannot
generalize it like that and it is the *design* that is the reusable
solution. If so, I agree.
public interface IProperty <T>{
public String getName();
public void setName(String name);
public T getValue();
public void setValue(T value);
}
public class Property<T> implements IProperty<T> {
private String name;
private T value;
public String getName() {
return name;
}
public void setName(String name) {
this.name = name;
}
public T getValue() {
return this.value;
}
public void setValue(T value) {
this.value = value;
}
}
public interface IFacet<S extends ISubstrate> {
public S about();
public Collection<? extends IProperty> getProperties();
public void setProperties(Collection<? extends IProperty> properties);
}
public class Facet <S extends ISubstrate> implements IFacet <S> {
private S substrate;
private Collection<? extends IProperty> properties;
public Facet(S substrate, Collection<? extends IProperty> properties){
this.substrate = substrate;
this.properties = properties;
}
public Collection<? extends IProperty> getProperties() {
return properties;
}
public void setProperties(Collection<? extends IProperty> properties) {
this.properties = properties;
}
public S about(){
return this.substrate;
}
}
public interface ISubstrate<T> {
public T self();
}
For more information on facets, refer to this
Wonderful Resource.
Posted by: javampire on September 20, 2004 at 07:06 PM
-
Easy to use little things?
Ah; learn something new every day. I see what the source of our misunderstanding is. There is a page on the c2 wiki that is devoted to a Facet pattern. I had no idea (but should have suspected) that someone else had defined the term already. Suffice it to say what Ward and company call a Facet is not what I am defining here.
Posted by: ljnelson on September 21, 2004 at 05:13 AM
-
Very interesting thread, probably dead now, but I wanted to add my 2c worth.
If you consider the problem of 'perception' or 're-cognition' along with the facet concept that you outline above, then you have a potentially powerful model.
Imagine the paradigm (or Universal) symbol for a pen, i.e. what is the general set of qualities that allow us to categorise something as a pen? Plato has the concept of the 'ideal form' of which the earthly concrete items are an imperfect reflection. The key thing here, and where I feel it ties in with your facets approach, is that the universal need not exist in reality, yet can be exemplified by the combination of facets.
If the facets are arranged into substrates the 'pen' concept becomes the collection of facets (as you say). Perception of a 'Pen' as opposed to a 'Pencil' then becomes the collection of a marginally different collection of facets. As Cognitive Psychology studies have shown, the perception is highly influenced by language and some cultures may not have a word (or different categorisation) of Pen and Pencil (or indeed any notion of either!).
This is obviously a huge topic, but I'd be more than happy to discuss it at length if anyone's interested. My final year thesis in my Computing degree in '88 was along these lines, but I never found anyone who quite 'got' what I was talking about.
Posted by: pjardine on April 21, 2005 at 03:54 AM
|