Relay-Version: version B 2.10 5/3/83; site utzoo.UUCP Path: utzoo!mnetor!seismo!rutgers!cbmvax!snark!eric From: eric@snark.UUCP (Eric S. Raymond) Newsgroups: comp.lang.c Subject: Re: portability and standards Message-ID: <107@snark.UUCP> Date: Thu, 2-Jul-87 22:25:52 EDT Article-I.D.: snark.107 Posted: Thu Jul 2 22:25:52 1987 Date-Received: Sat, 4-Jul-87 13:18:30 EDT References: <2290@calmasd.GE.COM> <4715@columbia.UUCP> Organization: Thyrsus Enterprises, Malvern PA 19355 Lines: 52 Summary: global variables considered harmful In article <3399@ihlpg.ATT.COM>, bgb@ihlpg.UUCP writes: > > [a sensible technique for preventing inconsistencies in globals usage] > I submit, though, that this whole discussion rests on a false premise -- that it is somehow a Good Thing to have a separate globals module with no code. Every time I've seen such a module it has been evidence for poor data design in the program. Globals are bad style, the data design equivalent of goto statements. Object-oriented languages like Simula, Smalltalk and C++ have demonstrated that the best route to a clean and powerful design is by partitioning that design into a set of communicating abstract data types -- black boxes with sealed innards and narrow, well-defined interfaces. [Yes, this is going to relate back to good C style in a bit. Bear with me...] The major difference between abstract data type (ADT) decomposition and the more primitive kind of functional decomposition that Algol-descended languages like Pascal and C were designed to support is precisely the status of global data. In an ADT design, data elements associated with a module are also considered 'inside the box', to be accessed through the same kind of narrow interfaces as the code elements. In languages like Smalltalk that were built from the ground up for ADT, every piece of storage is part of an instance of an ADT. There are no globals. This seems very odd when you're just getting used to ADT design, but once you get used to thinking in ADT terms you don't miss them. In fact, in an ADT design environment you quickly develop a perception that globals are ugly, because they represent places where the data elements of what should be ADTs are leaking into each other. [Returning to earth now...] C wasn't particularly designed for ADT building, but it's powerful enough to support it pretty well. In my C code, each .c source file implements an ADT and has an associated .h file that defines the interface. Each data area in the program is allocated in the module that defines the ADT it's part of. If it has to be accessible to other modules, it's declared (exactly once) in the corresponding .h file. There may be lots of data areas that are publically visible, but there are no 'globals' that aren't definitely owned by some ADT somewhere. I find this approach leads to code that is cleaner, better organized and much easier to maintain. The mental effort required to identify would-be 'globals' as part of an ADT including their handler code is usually fairly trivial, nor is there any run-time overhead necessarily involved in partitioning things this way. I recommend the elimination of globals, and the more general habit of thinking in ADTs, to C programmers everywhere. The grief you save may be your own.