The Design of Software (CLOSED)

A public forum for discussing the design of software, from the user interface to the code architecture. Now closed.

The "Design of Software" discussion group has been merged with the main Joel on Software discussion group.

The archives will remain online indefinitely.

OO Design Question

Say I have a bunch of related classes that all work together, that is, an object model. Each class will have various and sundry private and public members. However, I would like the private members of each class to be accessible to other classes. In other words, "private" members are realy semi-private: private to the user of the object model who cannot see them, put public to any of the members of any other class within that model.

The question: Is this design FUBAR, breaking encapsulation and defeating the purpose of OO, or is it a common pattern in OO? If the latter, what's the proper terminolgy, and do any OO languages support this concept of "semi-private" members?
The Dude
Thursday, January 25, 2007
 
 
IIRC, as long as all the classes are in the same package, they can (by default) see each other's members:

http://java.sun.com/docs/books/tutorial/java/javaOO/accesscontrol.html

I believe it is common practice to make member *variables* private (eg. accessible to nobody) but to make member *methods* protected or public.

Oh by the way... I am talking Java here specifically.
Greg Send private email
Thursday, January 25, 2007
 
 
In .NET, internal (in C#) or Friend (in VB .NET) is the term you'd use for this.  The members would be visible within their assembly (i.e. their DLL), but not to assemblies referencing that assembly (which would only see public members).
Kyralessa Send private email
Thursday, January 25, 2007
 
 
C++ also supports the "friend" keyword. However, the use of it is discouraged because it would make your classes tightly coupled.
dev1
Thursday, January 25, 2007
 
 
"However, I would like the private members of each class to be accessible to other classes"

Yes this is FUBAR.  By definition, a "Private" member of a class is NOT accessible to other classes.  That's what it MEANS to be "Private".

Now, you can make the members Public, in which case other classes can access them.  You can declare (in class A) that class B and class C are 'friend' classes, whereupon class B and class C can access A's private members.

This DOES break the encapsulation so important to OOD -- which is that classes are not supposed to directly access the data members of other classes, but instead call the public methods of the class.

Now, having said all that, I do find it helpful at times to make class members Public.  And having done that, it's now up to the 'politeness' of all other classes not to abuse that privelige, since I've given up the "Private" keyword which would FORCE them to go through a 'Getter' or 'Setter' method.

So I only do this when I find myself writing LOTS of 'Getter' and 'Setter' methods.  In other words, rarely.
AllanL5
Thursday, January 25, 2007
 
 
In general, any time I find myself declaring private methods, it is an indication that I really have a lower level class wanting to get out.  Try combining your private members into a class that is declared as a private variable within your other classes.
Wayne M.
Thursday, January 25, 2007
 
 
"This DOES break the encapsulation so important to OOD -- which is that classes are not supposed to directly access the data members of other classes, but instead call the public methods of the class."

If you're worried that friend classes could break OO design by introducing dependencies between classes, you must _really_ hate inheritance!

If two classes are sufficiently closely related that anyone would even consider giving them access to one another's internals, then it probably doesn't matter whether they're dependent on one another's implementation.  The purpose of encapsulation is to increase maintainability by ensuring that bits of code in very different parts of a program do not develop such dependencies, that users of a library do not make upgrades difficult, and so forth.

Short form: there is certainly nothing wrong with using friend methods in cases where this leads to clearer and more maintainable code.  If you want to hate something, hate code that's BAD, not code that fails to live up to some arbitrary concept of "purity".
Iago
Thursday, January 25, 2007
 
 
Nice try, Iago, but you were the first person to mention "inheritance" or child classes.

Meaning -- we're trying to prevent the exact 'bad' coupling you call out.  Of course it's appropriate for inherited classes, that's what it's there for.  But the OP wasn't about inheritance.  Or if it was, he certainly didn't mention it.
AllanL5
Thursday, January 25, 2007
 
 
Oh, and nobody mentioned "hate" either.  We're merely discussing different uses of different concepts, what is appropriate when, and what are the various drawbacks.

It's then up to the programmer to choose.
AllanL5
Thursday, January 25, 2007
 
 
"Is this design FUBAR, breaking encapsulation and defeating the purpose of OO, ..."

Yes; in C++ we call them friends :)
A. Nonymous
Thursday, January 25, 2007
 
 
This crops up every now and again -- rather than trying to stick to the rules, you need to try to find a global maximum (minimum?), such that the *whole* design is neat, even if this is at the cost of some raised eyebrows here and there.

And if you need to get there by tightly coupling a few things, then do that. The alternative is to bloat the public interface with the infrastructure to support what is actually a private matter between consenting classes... if 'friend' and its ilk is poor design, then that is far, far worse. (At least friend is explicit!)

From a more pragmatic perspective, it's my experience that friend classes usually come in groups. If you need one, you need them all. Whatever mechanism you use to link them, the coupling is inherent, so you might as well use a technique that results in the smallest public interface.

Of course, of course, if you don't really need friend, don't do it, etc. -- but it's there for a reason, and you're spiting yourself if you don't use it when it would make the end result better.
Tom_
Thursday, January 25, 2007
 
 
Thanks for all the comments.

AllanL5, I appreciate your comments and am sympathetic to your point. However, I think I agree more with Tom_.

Often an instance of a class can only come into existance through the method of a related class, yielding a parent/child relationship. (A typical example is an Excel Application, Workbook, Worksheet, Range...). Should the methods of a Workbook be restricted to only calling the public methods of a Worksheet? It seems no, but I'm open to argument.
The Dude
Thursday, January 25, 2007
 
 
Reuse is at the package level, not the class level, so there's no absolute rule that classes shouldn't touch each others privates, just a general taboo. Particularly if a class is an algorithm that operates off of data held in another class it's not uncommon to have close coupling.

For example, regular expression might touch the privates of string rather than have string expose internals or have string have every method in the world.

You could say that creates a future update anomaly and that's true, but it's OK. The package containing string and regular expression is what is released, so there will never be breakage for those dependent on it because users are still restricted to the public interface.
son of parnas
Thursday, January 25, 2007
 
 
BTW, this is the kind of question I would like to see asked in interviews. Something actually related to building software instead of creating castles in the air.
son of parnas
Thursday, January 25, 2007
 
 
The 'internal' access modifier is one of the things that makes me appreciate the .NET framework more than Java. It's just one of those nice little touches.

Sometimes it makes sense for the classes in one assembly to communicate with one another in ways that shouldn't be available to consumers of the API. Internal constructors, for example, are incredibly handy.
BenjiSmith Send private email
Friday, January 26, 2007
 
 
Hi all,
I think the solution is not using anything similar as package visibility offered by java or friend feature offered by C++....I think the solution is changing the design of the classes.
You are saying:
a)"private to the user of the object model who cannot see them"
b)"but public to any of the members of any other class within that model."
I see here cleary 2 concepts mixed in one...you have a coffe machine but you would like it do tea also, but only for a few selcted well known friends :-D...it's imposible in real life...and it's not good OOP.
Your words scream clearly for two interfaces:
a)UserInterface (which declares only the public methods you have right now)
b)InternalInterface(which declares the private methods you have right now and desire to be saw internaly, it may also be derived from a if you need it.)
So, i would advise you, for each class you have right now, to create 2 interfaces (a and b) and to derive the current classes from this interfaces.
This concept will also alow you to have real private members in the class...featrue that friend and java's package visibility does not offer.
This approch may take longer to develop, but in time will payback a lot...trust me :)
Megabyte Maniac Send private email
Friday, January 26, 2007
 
 
> ... a bunch of related classes ...

It's common for *nested* classes to be friends.

class Container
{
  class Containee
  {
    //Container can access privates of its Containee instances
    friend Container;
  ...
  };
  class Iterator
  {
  };
  //Iterator can access privates of the Container instance which it's iterating
  friend Iterator;
  ...
};
Christopher Wells Send private email
Friday, January 26, 2007
 
 
Use interfaces to control visibility!!!

public interface A {
  void foo();
}

public final class AFactory {
  private AFactory() {}

  A build() {return new AImpl();}
}

// Non public but visible at the package level.
class AImpl implements A {
  // visible at package level.
  int dataMember;
  void foo () { // }
}
Dino Send private email
Tuesday, February 06, 2007
 
 

This topic is archived. No further replies will be accepted.

Other recent topics Other recent topics
 
Powered by FogBugz