Relational rather than hierarchical OO packaging?

Nothing stunning here, just a basic/simplistic question -

Assuming relational better than hierarchical, for "visibility" of things in languages, are there / could there be a successful approach to visibility of things which is relational, not hierarchical?

C++ has the "friend" visibility keyword, Java and C# don't seem to have a cross-cutting visibility tool. Does C++'s "friend" suffice, or does it have too much of a preference of hierarchical over relational, and/or does it have some land-mine drawbacks (I mean besides the standard chances of abuse)? I guess I was always just queasy with it e.g.

If encountering friend functions for the first time, you might feel slightly uneasy since they seem to violate encapsulation. This feeling may stem from the fact that a friend function is not strictly a member of the class.

By thinking of a friend function as part of the classâ€™s public interface, you can get a better understanding of how friends work. From a design perspective, friends can be treated in a similar way to public member functions. The concept of a class interface can be extended from public members to include friend functions and friend classes.

Comment viewing options

I guess it depends how you use it

Another quote from the article:

Another reason for using a friend function is one of efficiency: directly accessing data members saves the overhead of using get/set members, if the compiler has not inlined these

Now if that does not invite violations of encapsulation...

Note that C++ has private and protected, so that is not as if hierarchical visibility would not allow for some encapsulation itself.

Classes are not always proper abstraction boundaries...

...often times, you want abstraction boundaries to not be congruent with (natural) classes.

There are many good reasons, in C++, to define free functions which are friends of a particular class--to assume that doing so violates modularity is only true if a) you assume that the class is the only proper abstraction boundary, and/or b) do something silly like letting somebody else specify the implementation of a friend. But if the class and the friend function are part of the same "module" (here in quotes as C++ doesn't have modules or packages), and developed and deployed in tandem, there is no abstraction violation.

The same is true in the opposite direction--there are many times that I want to grant access to a particular attribute in a class *only* to a few select methods; and want to prevent access to the attribute by any other class member (let alone an external client).

IMO, "protected" is often a bigger violation of abstraction than "friend" is.

b) do something silly like

b) do something silly like letting somebody else specify the implementation of a friend.

There is something to be said about keeping related code in the same source file ;)
Who knows who will revisit your code after you wrote it?

Or not use files at all

It always seemed to me that sorting code into files is a little odd. Especially since the ways that we need to access definitions are much more like searches than reading a book.

Visual Age

I think Visual Age IDEs used to show you a more fragment (by method) view of the source code. It was a little annoying because sometimes I really do just like to scroll through the whole file to try to get the gestalt of things, and because I'm relatively good at maps+directions so once I know the layout of a file I can find what I want by direct navigation rather than search.

Basically the idea of One Way To Do It when it comes to viewing code is probably wrong; it would be nice to enable many different views of it. Like, sometimes I want to see the subclass as if it had all the parent class code inlined in it.

Eiffel does that sort of thing...

IIRC, the Eiffel tools from Betrand Meyer's company allow four views of a class--the product of two orthogonal parameters:

* Whether all features (including private one) were shown, or the public interface only

and

* Whether or not the "resulting" class (containing all base class features not overridden or renamed), or just the class definition itself (showing only changes from the base classes)

Of course, such a feature is not technically limited to Eiffel.

Thanks for the notes

It seems to me that, even with things like "friend", C++/C#/Java start off with and mainly stick to the hierarchical meme. Are there approaches to code visibility which start with something else instead? (e.g. relational, network.)

Hierarchies...

In many OO languages, there arenot one but two hierarchies present: The inheritance hierarchy (which is often not a hierarchy but a DAG, in OO languages with multiple inheritance), and the scoping hierarchy (which remains tree-structured FTMP; though languages with delegation may also exhibit DAG-structure here as well).

I'm not aware of any languages in which visibility is based on the relational model. I'm sufficiently unfamiliar with "network databases" (other than RDBMS dogma that they are bad) to comment there; though capabilities (you can see things that you hold references to; there is no global ambient authority available through queries over a namespace or a set of relations) might suffice for an example of a "network model".

I'm not sure that a full-blown relational model (or a Prolog-style inference model, etc.) would be all that beneficial--such a thing might well be harder to specify and/or make secure rather than easier. What is the use case for such a thing?

Use case?

Partly just a thought experiment. But, there are times when I want some part of something exposed to some part of something else, and in Java/C# I guess it would generally require either opening up everything, or making various adapter classes. Neither is an attractive option.

On the other hand, I do wonder if a relational visiblity system would simply lead to a rat's nest of completely non-un-tangle-able code.

Friend in C++

lets you expose all of something to part of something else; though the "something else" is limited to either an entire class (which is often too coarse), or a list of specific methods within that class.

Friend does not, however, let you open up only part of a class's implementation to the designated friend--any class/method declared a friend has access to the entire stinking class

You can do that, albeit

You can do that, albeit clumsily, in Java by resorting to the (default) "package" visibility.

Packages

I always stressed to my students that Ada uses the package construct for visibility, and tagged types for inheritance thus cutting the Gordian knot tying these two aspects of OOP in class based OOPLs.

In Ada, for example, two tagged types (classes) can be defined in the same package, and thus visibility exists between the implementations. If you don't want that (as is usually the case), simply define the types in separate packages.

Traits

There are many known problems with using classes as the unit of code reuse and abstraction. Many such problems are solved by traits, and I believe they solve this "friend functions" problem as well.