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.

protected variables feels just as bad as public

I am getting a littled concerned about protected variables. As I understand they are used to allowed derived classed to access them. I am working in a project where there a somewhat deep inheritence hierachy (A widget-toolkit in C++), perhaps 5 or 6 levels. What I see is this:

A lot of the subclasses are using protected variables in superclasses that can be 3 or 4 levels above them in the class hierachy like if they were declared in the subclass.

This feels almost as bad as if the variables were public in my eyes. If the variable is declared in the superclass, shouldn't it only be used by functions in that superclass then? A tight coupling is created.

So my questions are these:

*) Is my analysis correct, are protected variables generally bad? Or is there something I missed?
*) If I am correct, what is a proper use of the protected functionality?

Thanks.
Nick Send private email
Thursday, June 08, 2006
 
 
With protected properties, you're exposing the inner workings of your class with any subclasses.  It has it's uses but if you want as much decoupling as possible than obviously protected properties are going to be an issue.

I find my need for protected properties pretty low -- I try and expose an API of protected methods to any subclasses so they can avoid knowing too much about the base class.
Almost H. Anonymous Send private email
Thursday, June 08, 2006
 
 
==> A tight coupling is created.

I hate to be playing "Captain Obvious" here, but ... isn't there already a tight coupling -- the fact that "inherits" is about as tightly coupled as one can get?

Methinks you're worring about the wrong thing here. It's already waaaaaayyyyyyy tightly coupled, doncha think?
Sgt.Sausage
Thursday, June 08, 2006
 
 
A class is tightly coupled to itself, yet some people still write private accessors and mutators.

Or is that just me?
DHofmann
Thursday, June 08, 2006
 
 
"the fact that "inherits" is about as tightly coupled as one can get?"

What makes you say that?  Inheriting from a class is only slightly more coupled than containing a class.
Almost H. Anonymous Send private email
Thursday, June 08, 2006
 
 
> the fact that "inherits" is about as tightly coupled as one can get?

If 20 different programmers are deriving from your class not breaking their code is a good goal. Not using protected means you are more isolated from implementation changes, which is a good thing.
son of parnas
Thursday, June 08, 2006
 
 
There is no good reason to ever have protected variables in C++. If you definitely need them, I would wrap private variables in protected accessor functions. Although this does not reduce the coupling it improves encapsulation.

There are various reasons for using accessor functions, even  private ones. It makes it easier to track down who is accessing the variable when. It permits to change the internal representation of the variable (say, you have a read-only double and now decide that it should be implemented as a property of another object.) It allows you to add consistency and validity checks.

The cost is to have to write at most two accessor functions, which usually can be automated to cost one or two keystrokes.
ILoveFortran
Thursday, June 08, 2006
 
 
Since inheritence breaks encapsolation, then yes - protected (of non final) variables isn't good. Unless the variable is final, it should never be exposed directly, since you're just asking for trouble. They've exposed implementation details that, if ever changed, they will forever have to make nasty work arounds for legacy users. That's doable with protected methods, but downright painful if the variables are exposed. Definately a no-no.
Manes
Friday, June 09, 2006
 
 
Protected variables means that the subclass can change behaviour in ways that you haven't predicted: which can be good or bad.

If it's a commercial library that you're writing, then you may not want to define protected variables: because you don't want variables (i.e. your implementation details) to be part of your supported API (i.e. you might want to change your current implementation in your next release).
Christopher Wells Send private email
Friday, June 09, 2006
 
 
It sounds to me like your package may be relying too much on inheritance to begin with. If you haven't already, invest in a good Design Patterns book ("Design Patterns", "Patterns of Enterprise Application Architecture") to find alternative ways of accomplishing goals without using inheritance. The PROXY, DECORATOR, and VISITOR patterns can often be excellent alternatives to subclassing, thereby resolving your coupling issue.
Chris McKenzie Send private email
Friday, June 09, 2006
 
 
""the fact that "inherits" is about as tightly coupled as one can get?"

"What makes you say that?  Inheriting from a class is only slightly more coupled than containing a class."

Man, AhA, I can't believe you said that.  "Containing" a class means you have to instantiate one, or add a reference to an existing one.  It means you have to comply with the interface provided by the class.  The "Has-A" relationship applies.

Inheriting a class means the 'Is-A' relationship applies.  The new class IS an instance if the inherited class, and IS an instance of every class the 'parent' class inherited from.  That's what polymorphism is all about, after all.

And yes, the "Is-A" relationship is way more coupled than the "Has-A" relationship.  Even if you try to "break" that coupling through preventing child objects from accessing parent properties.
AllanL5
Friday, June 09, 2006
 
 
I think Ruby has the right idea: all member variables are private, period. There's no way to designate a member variable as public or protected, so if you want it accessable, you have to write accessor methods. But there's a shortcut for automatically generating accessor methods so that you don't have to waste precious time or lines of code writing them manually.
Karl von L. Send private email
Friday, June 09, 2006
 
 
protected variables are a pragmatic choice.

That is to say, they do not lend themselves to the diamond like jewel of software engineering theory, but they help get the job done.

Think of a library which is treated a true library (perhaps even the library might be compiled into a DLL), in a sense that most other class libraries are not. What I mean by this, is that everybody who uses the library, actually uses it as a library, warts and all - and doesn't recompile it or alter its APIs, add class members, etc.. Compare: Most class libraries, especially class libraries developed within companies, are not really treated as libraries by the programmers who use them - when they're developing their app, if they don't like something in the library, they want a new method, etc., they go and modify the library and recompile it.

Now, if you want people to be able screw around with the internals of a class in this type of library, as a last resort, but generally otherwise discourage it,  then you'd use protected for your variables instead of private
S. Tanna
Friday, June 09, 2006
 
 
"Man, AhA, I can't believe you said that."

Well, I do know the difference between Is-A and Has-A here Allan.  If you contain a class you have an instance of it and you can only call public methods of that object.  Putting aside the polymorphic implications of inheriting from a class, you have nearly the same coupling.  You have a single "instance" of the parent class (ok, it's your class) and you can call protected and public parent methods.
Almost H. Anonymous Send private email
Friday, June 09, 2006
 
 
> And yes, the "Is-A" relationship is way more coupled
> than the "Has-A" relationship.

What makes it more coupled? You are pretty much just stating it is so and providing definitions.
son of parnas
Friday, June 09, 2006
 
 
When discussing how coupled something is you have to think about the context of the difficulty in making a certain  type of change to the system. Everything is coupled. The issue is how it is coupled in the face of change.

The "is-A" relationship is more tightly coupled against changes in the base class implementation.

The "has-A" relationship is more tightly coupled to the interface that you create as the usage pattern between the two classes. 

Both produce coupling but in different ways. So when someone says that one or the other produces "more coupling" you just have to ask "for what scenarios?".
anon
Friday, June 09, 2006
 
 
> The issue is how it is coupled in the face of change.

Bingo.

> against changes in the base class implementation.

Only if you play with the privates.

> "has-A" elationship is more tightly coupled to
> the interface that you create as the usage pattern
> between the two classes.

Which is why changes in hasa can cause more change to your code because you are forwarding calls to the hasa code in your code. Externally you interface may not change, but internally a change may cause a great deal of churn.
son of parnas
Friday, June 09, 2006
 
 
I agree son of parmas. And I'd also say that my examples may not have been the best one's available for proving a point one way or another. But hopefully everyone understands what I was going for.

And for what it's worth, I hate hearing the argument that "inheritance is evil". It just isn't so. Like all things it has its place and can easily be abused. But it is a necessary part of a true OO solution. You just have to use it in the right scenarios.
anon
Friday, June 09, 2006
 
 
I guess you're right, I hadn't proven my point.

My point being, a "Has-A" depends on the Public Interface, exposed by the Public methods of the class it 'has'.

An "Is-A" depends on all the methods of the parent class, as well as methods of that parent's class parents, if any.  And I believe it was intended to be used that way.

So (in my view) "breaking" that dependency of a child class on a parent class's properties, by declaring them private in the parent class, also 'breaks' that inheritance model a little.  And it's justifiable in many instances.

But in any event, since the child is dependent on all the methods of the parent class, while the 'Has-A' is only dependent on the Public methods, therefore the child is more tightly dependent.
AllanL5
Friday, June 09, 2006
 
 
A "has-A" depends on public the methods of the contained class, as well as the public methods of that contained classes parents, if any.

"since the child is dependent on all the methods of the parent class, while the 'Has-A' is only dependent on the Public methods"

How is the child dependent on *all* the methods of the parent class?  Surely it's only dependent on the protected and public methods?  And it's doesn't seem like it's more dependent -- it is, as anon says, dependent on how the classes are used.

So we've added protected in the mix -- which are specifically included in the parent class for the purpose of being used an interface by subclasses.  There really isn't that much more coupling and it's certainly not unexpected by the parent.
Almost H. Anonymous Send private email
Friday, June 09, 2006
 
 
To answer the original questions:

>> *) Is my analysis correct, are protected variables generally bad? Or is there something I missed? <<

Yes, protected variables are generally bad.  Your analysis is absolutely correct.

>> *) If I am correct, what is a proper use of the protected functionality? <<

You should use "protected" for *methods* that comprise the interface to the class that's intended for inheritors of the class but not users of the class.
SomeBody Send private email
Friday, June 09, 2006
 
 
I understand this is done to protect the class from some programmer who, theoretically, could break the inherited functionality by changing the member fields in a descendent class.

However... after way too many cases when I had to revert the member visibility to "protected" or curse the library programmer for making something private which resulted in me dancing complicated figure-eights around that with accessor methods where I only needed a direct read of the data... I reconsidered. A descendent class is just that - a descendent of another class, a version thereof, and should not break the "is a" relationship by hiding data from what is, essentially, the same class with adjustments or extensions.

I do use private things, still, but only for the data which is incidental for a particular descendant. If I introduce something that is essential for the class's functioning, it is protected. If it is a class that implements a vector of pointers, then I do not hide the actual vector from descendants.

If you feel that such access can break your class, consider a "has a" relationship instead, which is an interface contract, not a version. Protecting programmers from themselves is good, but it is not properly done by limiting their options.
ping?
Friday, June 09, 2006
 
 
+1 for "ping?".

I know we seem to be going in two directions here.  Direction one is "Keep Parent Properties Private" (which I disagree with, but others seem to like).  Direction two is "Most Parent Properties should be Protected" to let children access them -- after all, they're descendents, why did you make them descendents if you didn't want them to inherit? (which I agree with, but violates the first approach).

Apparently, this dichotomy is revealed when people use inheritance to use interface library code written by somebody else.  Fair enough, when this is the case, the 'parent' data needs some protection from mis-guided children, and 'private' gives you that.

I guess the point for the OP is that there is disagreement about this.
AllanL5
Friday, June 09, 2006
 
 
Oh, and to answer the second question the OP asked: personally, it seems appropriate to make properties "protected" when you ARE using polymorphism.  That is, when you create a stack or tree of the 'base' class, and fill it with instantiations of 'child' classes.

Then each 'child' can know how to 'draw' itself, looking like it 'owns' its own properties, even though those have actually been inherited from some 'parent' class.
AllanL5
Friday, June 09, 2006
 
 
When designing my own inheritance tree, it's pretty much open season.  There is explicit tight-coupling between the base class and child classes.  There are lots of cases where this is appropriate (probably far more than the other case).

In some places, say for example a GUI library, where controls inherit from a base Control class then protecting the child controls from the implementation of the base Control is probably far more important. 

In either case, it's the coupling is the programmer choice and has nothing to do with whether it's a Is-A or Has-A relationship.
Almost H. Anonymous Send private email
Friday, June 09, 2006
 
 
Agreed.  Sorry to chase the "coupling" wild hare.
AllanL5
Friday, June 09, 2006
 
 
Hi again, thank you all for your advice and comments. I do not know if I got any wiser though as there does not seem to be a clear answer. Anyway, I thought I would expand somewhat about the original problem I mentioned at the beginning.

What we are doing in our project is to implement a widget-toolkit from a existing API. This API is used by a lot of internal applications and our job is to produce working implementation of it. The implementation should be as close the specification of the widget-API as possible.

To accomplish this a design has been made where the different entities of the api are reflected as different classes (widgets, windows, menues etc). I have not been involved in creating the design and large changes to it is not an option at the moment. The design uses inheritence a lot (window is-a widget, menu is-a windows etc..). A lot of the variables in the base-classes are protected and liberally accessed in the sub-classes. This caused what I perceived as the original problem. It is common that one, two or more subclasses access a protected variable in a baseclass.

This makes is difficult for me to understand what is happening when I find a variable being maniplated in a class. I need to look all over in order to see how it is used. And even when I have looked everywhere, the complexity of all this functionality spread out all over the place makes it very difficult for me to be confident that a change I make is correct. On top of this we are using a very complicated language as well, C++.

So, this is the situation that spawned my original question. English is not my native language so you will have to excuse me if I something is unclear.

Many thanks everybody for your very knowledgeable answers
Nick Send private email
Saturday, June 10, 2006
 
 
"Is my analysis correct, are protected variables generally bad? Or is there something I missed?"

In your case, I think that accessing the protected variables are bad.  There isn't a hard-and-fast rule here and it depends on how the classes are used (and who is using them).  Because you're exposing an API to be used by way of inheritance, you'd be better off making all the variables private.

"If I am correct, what is a proper use of the protected functionality?"

You should create protected methods to provide an API for the subclasses to use.  Rather than being able to access protected variables directly to affect changes, the subclasses must call your methods to do anything.
Almost H. Anonymous Send private email
Sunday, June 11, 2006
 
 
The goal of making the members private is to encapsulate them from inheritors, as a method to reduce coupling.  Reducing coupling lets us get something done more quickly, because we can reuse code.  Having them be protected is more of a pragmatic, "we have to deal with this somehow" thing, at least from what I read above.  So, our goals are "decouple (to get something done faster)" and "get something done (now)."  Seems like we both want to get something done. 

Herein lies the problem.  Some of us like the first way, some of us like the second.  Because there is no way to tell which way the author(s) of the library you are using felt, you can't make assumptions about how to work with it.  We can't mix and match the two approaches (and their varying degrees in between) perfectly.  Because we can't mix and match, we are cutting down the effectiveness of decoupling in the first place, which is code reuse to get something done faster.  This creates a lot of "glue" code between libraries and their consumers, which again cuts down our productivity (and increases the possibility for bugs, and testing time).  Is it any wonder that the "not written here" approach is so common? 

By definition inheritance programming is differential programming.  It is going to be more highly coupled that if you just wrote your entire class from scratch (reimplementing all the functionality in the parent in the child).  Because we would rather reuse the parent class, it is better to give the programmer more control over the things in it than to try to prevent him from hurting himself.
Joshua Volz Send private email
Sunday, June 11, 2006
 
 
"And yes, the "Is-A" relationship is way more coupled than the "Has-A" relationship."

That's incorrect. Think in terms of testing:

class A
class B extends A
class C extends B
class D extends C

A changes => retest A, B, C, D

class A
class B has-A A
class C has-A B
class D has-A C

A changes => retest A, B, C, D
Dino Send private email
Monday, June 12, 2006
 
 
What's protected for?

// Contract
public interface A {
  void foo();
}

// Blueprint
class AbstractA implements A {
  public void foo() {
    knownBehavior();
    abstractBehavior();
  }

  private void knownBehavior() {
    ...
  }

  protected abstract void abstractBehavior();
}

// Implementation
class ConcreteA1 extends AbstractA {
  protected void abstractBehavior() {
      // Implementation A1
  }
}

class ConcreteA2 extends AbstractA {
  protected void abstractBehavior() {
      // Implementation A2
  }
}
Dino Send private email
Monday, June 12, 2006
 
 
+1 for "Almost H Anonymous"

IMO, if you're going to use 'protected' anything, it should be a method (member function) NOT a variable.

Remember that the member data is, collectively, supposed to represent the VALID state of an instance.  By exposing the data members directly to deriving classes, you invite the possibility that a deriving class could put an instance into an invalid state.

Methods (public and protected) are a contract for client code and deriving classes.  Exposing member data allows the same to violate the contract.

Just say NO to protected variables.
Anon for this post
Thursday, June 15, 2006
 
 

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

Other recent topics Other recent topics
 
Powered by FogBugz