We subscribe to the maxim that ``pointers are the root of all evil.'' In the 1970s, computer researchers developed a disciplined approach to procedural programming called ``structured programming'', which imposed an orderly structure on the control flow of programs. Up until that point, languages (and programmers) relied on the notorious goto statement, also known as the unconditional branch to specify control flow. The undisciplined use of this feature leads to ``spaghetti code'' in which control flow is almost impossible to trace by hand, making the code very difficult to debug. In his Turing Award Lecture in the early 1970s, C.A.R. Hoare observed that pointers in data structures were the analogs of goto statements in control flow. With pointers, a program can create many different references to the same mutable data object, making the effects of data mutation very hard to follow and data mutation errors very hard to debug. When multiple references exist to the same mutable object, it is easy for one section of the program to break a data representation invariant assumed by another section of the program. For example, one class might delete a node in a shared list that another class presumes is immutable.
Even in programs written and maintained by a single programmer, the unrestricted use of pointers is foolhardy and invites disaster. A programmer almost certainly does not remember the precise reasoning used involved in writing every line of code in the application. As a result, mistakes are inevitable. Just as structured programming placed constraints on the control flow in programs, we will restrict the use of mutable pointers by embedding them in objects and only providing mutation operations that maintain the invariants associated with the objects.
In the case of a class implementing a mutable list, no code outside the class should modify the pointer fields used to represent a list. Hence, we must either (i) prevent Node objects from being returned as the results of class operations or (ii) use a public interface to Node objects that only only includes operations that do not mutate the structure of the list. For the sake of simplicity, we choose the first option. We can define the node class as a private static nested class of the list class.