After my last post, I started thinking about how often I've run into a situation where the notion of "groups" complicates what would otherwise be a simple process. The classic situation is is that the user wants to perform an action on an element, but that action is group-associative, not element-associative. So, in order for the user to do what she wants to do, she has to stop mid-process and create a new group.
Of course, one common solution to this problem is to treat elements and groups essentially the same way. This can be most simply expressed by making each element a group of one and by making groups able to contain other groups. This solves most of the problems, but it adds a layer of complexity and dilutes the meaning of group membership. Instead of of carrying semantic weight, groups become something more akin to a shortcut.
I think that a better way to represent this kind of relationship is to associate capabilities directly with elements and to avoid groups. This kind of distributed system is more flexible and runtime-y. It may slow down queries like "who are all the users who have this capability?" but it makes most operations simpler.
What's interesting to me is that these alternate strategies for distributing capabilities across elements in a system mirrors closely the divide between rigid, class-based OOP systems and a prototype-based approach, where prototypical objects specify shared behavior. I guess it's no surprise that my preferences are consistent across both the categorization of shared properties and meta-object protocols.
It occurs to me that this dichotomy between aggregration and distribution is something very deep -- something that goes far beyond software development to the essential way that we perceive commonality. I asked Oliver Steele about this, and he told me that this is actually an area of study for cognitive psychology and linguistics. I took a moment to look at the divide between the classical view of categorization and the more modern Prototype view advanced by Eleanor Rosch.
This is fascinating stuff. At a fundamental level, it asks: do we perceive the magnolia tree in the front yard as "a tree" because it has the attributes we associate with the abstract set of qualities that define "tree-ness", or because it matches with some degree of affinity to the idea of a concrete and prototypical tree that each of us are carrying around in our heads. My own sense of this leans leans strongly towards the latter, but I'm a bottoms-up designer and a client programmer and I recognize that there are people out there who really do start with the abstract and move to increasing levels of concreteness and detail.
Similarly, my personal experience suggests that groups never do a good job of modelling the real world. The evolution of file access permissions from group-based to access control lists would seem to reinforce this position. Of course, there is value in creating shortcuts so that a user can, say, send an email to all the people working on a given project, but I usually find that the membership in that group is so flexible, and that the UI that represents that group so inflexible, that it's not worth it to set up and maintain that shortcut.
Like any dichotomy, grouping and distribution represent two sides of the same coin. All of the elements that share a distributed direct object are a group, but in the same way that changing a variable name can suddenly point the way to refactor a method, the right conceptual model for a relationship in software can lead to simpler, shorter, and more maintainable code.
At an even higher level, concepts like this are a lot of what I like about software engineering. Code makes us treat abstract concepts in a concrete and rigorous way. Software patterns go beyond semiotics, and beyond even cognitive science and linguistics, to formalize some of the essential patterns of our perception.