Subject: Re: Remove Coding Assignment Comments
From: Matthew Cary (cary@cs.washington.edu)
Date: Fri Apr 26 2002 - 10:59:27 PDT
Below is a question recently posted to the cse326@cs list. I think the
points raised by it are important, so I'm posting a fairly involved
response.
> I used the methods of the class, because I was advised to, but I see no
> reason. Professor Cary used l, r, and parent in his class methods.
> Regardless of being public, private or protected, we were implementing a
> method of the class (given away by the TreeNode and scope resolution
> operator). Why do we use the methods when we are building a method? I
> didn't understand that at all. Maybe I'm just confused, but I found it
> a really weird way of implementing a class and have never seen it done
> that way before.
>
Here is what one of the Set* methods looks like. I believe you have all
of this code in the AVL project.
void TreeNode::SetRChild(TreeNode *p)
{
if (r && r->parent == this)
r->SetParent(NULL);
r = p;
PositionRChildren();
}
This deals with positioning nodes on the screen when they're drawn. Thus
you can see that directly assigning into r or l would have caused the tree
to be displayed incorrectly.
It turns out that the accessor methods (LChild(), RChild(), Parent())
don't do anything other than returning the node. Suppose this
changed---there might have been a bug in *my* code that required me to
change the accessor methods to do something fancier---then those functions
of yours which directly accessed l, r and p would have broken.
In fancy terms, accessor methods and the Set* methods provide
encapsulation, and if you directly access l,r, and p, you are not
respecting the encapsulation. This is poor programming practice.
C++ has language features that support encapsulation--for example, public
members vs. private members. The way the TreeNode class was written did
not take advantage of those language features. This does not mean that
there was no encapsulation (in fact, in the homework problem due today of
designing a tree object hierarchy, this would have been a good point to
notice and repair. A better class hierarchy would have used the C++
language features for encapsulation for your assignment---an early version
of the assignment did this, but I changed it because it caused other
design issues to come up).
Good programming practice does not depend on language features. Just
because you can access a member, does not mean you should access a member.
Part of being a good programmer is understanding when and how to
encapsulate, even when it's not syntactically necessary.
In many ways, the TreeNode class I gave you is not a good example of a
class. The one advantage to it that I can see is that you were able to
add node removal with a minimum of overhead. A major disadvantage of the
class was that encapsulation was not well-integrated with C++. The
methods you were implementing had access to private class data (by virtue
of being class methods), even though they should have been written using
only public methods.
This is a situation you will come across very frequently. The most common
task of a professional program is to extend or maintain somebody else's
code, and that code is usually not perfectly written or designed. A good
programmer is in the habit of figuring out what the encapsulation scheme
is---regardless of whether it's integrated with the language being
used---and respecting it.
Note this means more than just using LChild() because I told you to. It
requires recognizing that accessing or changing node pointers involves
updating the display of the tree, and that your code should be as
independent as possible from the code used for the Visualizer.
This is a somewhat long-winded answer. The reason why I'm giving it is
because we're not really able to spend time on software engineering in any
of the 300 level courses, even though it is one of the most important
things for you to learn, as a long-term programming skill. There's a
chicken and the egg problem. The programming done in 142 and 143 is too
small-scale and trivial to really require well-engineered software and
good programming practices. Only after you've been through the 300
sequence have you been exposed to software systems of enough complexity
that the need for software engineering makes sense---and the way the 300
series is structured, there's not much space for teaching software
engineering.
Even though I'm not going to lecture on program design, it's important for
you to apply the design principles you've learned in 142 and 143, and
other 300-level courses, to your programming projects.
Matt
This archive was generated by hypermail 2b25 : Fri Apr 26 2002 - 10:59:37 PDT