Object vs Procedure

I observe that many students present a procedure as if it were a class. Although, in programming, students may define a class as they wish, some class modeling is preferential to the rest.
 
Consider that we have a binary-tree data structure T, and a set of procedures such as NodeAddition() and NodeDeletion() that manipulate T.  There are a few choices in terms of modeling or design or programming. To make our dicussion clearer, let us assume that there are many such binary-tree data structures to be maintained by a program. Suppose that such a binary tree data structure can be referenced by a user-defined type Btree.
 
Choice 1 (Poor): We keep T as a globally accessed data structure. In this case, to manipulate T, NodeAddition(Node n) and NodeDeletion(Node n) need to know a particular binary tree to be manipulated. To do so, we may revise these two functions so that each of them accepts a binary tree as an input. The results are NodeAddition(Btree T, Node n) and NodeAddtion(Btree T, Node n). 
 
Now, suppose that we want to add a node x to a tree T1 followed by removal of another node y. We may implement the sequence of operations as follows:
 
                    NodeAddition(T1, x);
                    NodeDeletion(T1, y);
 
Suppose further that we implement each procedure as a standalone class, then we may codify the above sequence as follows. Moreover, to make the sequence of code meaning in program, let us put it inside another method F().
 
   F(BTree T1, Node x, Node y ){
                  O1.NodeAddition(T1,x);
                  O2.NodeDeletion(T1, y);
    }
 
The key data structure T1 is implicitly shared by two objects, yet T1 itself is explicitly shown publicly and visible to F(). Any change to T1 (such as changing from Btree to B+tree as the user-defined type) will affect O1, O2 and F. It is undesirable.
 
Choice 2 (Satisfactory):  On top of the example illustrated in Choice 1, a better solution is to hide T1 from F. To do so, we need to make T1 to be shared implicilty between NodeAddition() and NodeDeletion(). In other words, we need to remove the Btree parameter from the input parameter of either procedure.
 
We may combine these two classes to form a brand new class that has two methods Add(Node x) and Delete(Node y). Let us call this class Tree. So, somehow, we need to set up the Btree (i.e., passing T1 to an object of Tree) before the possible operations Add(Node x) and Delete(Node y). We then replace O1 and O2 by O3, and we have:
 
    F(Tree O3, Node x, Node y ){
                  O3.Add(x);
                  O3.Delete(y);
    }
 
So far, the class Tree has the format of a class, but it lacks in the spirit because the data to be protected by the class is a globally accessible data structure T1. So, if we inspect the code of a simple program, we may identify the sequence of Add() and Delete(). However, just based on these sequences, we are not sure whether the target binary tree (T1 in our case) has been manipulated correctly. One noticeable problem is that T1 (being globally accessible) can be manipulated by some other procedures that both the developers of the Tree class and the developers of those classes that use the Tree class do not know them. It is risky to use the Tree class.
 
Choice 3 (Excellent): To produce defensive code, we should have better put T1 as a private attribute of the Tree class. In this way, there is no way for the other classes to access T1, except invoking the Add() and Delete() methods of the Tree class. By enforcing such a constraint in a program, the developer of the Tree class can completely control how to manipulate the private attribute. Moreover, the developers who use the Tree class may have more confidence to reason their own code by studying the sequences of operations acting on the Tree class.
 
In short,  do not share any secret among classes. Keep each secret within exactly one class privately.

Selected Tags

Tag Groups

Links

ACM SigSoft
IEEE Software Engineering Online