From mboxrd@z Thu Jan 1 00:00:00 1970 X-Spam-Checker-Version: SpamAssassin 3.4.4 (2020-01-24) on polar.synack.me X-Spam-Level: X-Spam-Status: No, score=-1.9 required=5.0 tests=BAYES_00 autolearn=ham autolearn_force=no version=3.4.4 X-Google-Language: ENGLISH,ASCII-7-bit X-Google-Thread: 103376,63a41ccea0fc803a X-Google-Attributes: gid103376,public From: Matthew Heaney Subject: Re: Naming of Tagged Types and Associated Packages Date: 1998/08/09 Message-ID: X-Deja-AN: 379320372 Sender: matt@mheaney.ni.net References: <6qfp80$p0u$1@nnrp1.dejanews.com> <35CD0A8E.21D64380@sprintmail.com> NNTP-Posting-Date: Sat, 08 Aug 1998 21:43:57 PDT Newsgroups: comp.lang.ada Date: 1998-08-09T00:00:00+00:00 List-Id: "John G. Volan" writes: > Matthew Heaney wrote: > > I usually qualify auxiliary types with the name of the "main" type, so I > > probably would have named the type Car_Steering_Wheel, and the object > > Steering_Wheel. > > > > package Cars is > > > > type Car_Steering_Wheel is ...; > > > > type Car is > > tagged record > > Steering_Wheel : Car_Steering_Wheel; > > end record; > > > > This is the convention used in package Text_IO, for type File_Mode. > > > > This is another reason why use clauses are safe. The naming convention > > makes it obvious that type Car_Steering_Wheel is declared package Cars. > > Matthew, you seem to be confusing P. Doyle's point. (You seem to have > lost something in translation from Eiffel to Ada, not surprising.) I'm > fairly certain that P. Doyle intended the "STEERING_WHEEL" type to be a > primary type in its own right, declared within its own module, and not > some auxiliary type subordinate to the "CAR" type, somehow declared > within the same module. (In fact, since P.D.'s example was Eiffel, the > "STEERING_WHEEL" type would _be_ its own module). Your point highlights a difference between the two languages. In Ada, it's very natural to declare related ("cohesive") types in a single module. I was proceeding under the assumption that steering wheel type didn't stand on its own; that it supported the larger car abstraction, and hence was declared in the car module. This is a very common idiom in Ada, where you have a single module that exports one or more primary ADTs, supplemented by auxiliary types that describe attributes of the primary abstraction(s). > So your answer begs the question: What, then, would you call an instance > of the "CAR" type? > > In Eiffel, the answer is fairly simple: > > car : CAR > > The equivalent in Java would be: > > Car car; > > (Let's please assume that we're in some context where there is only one > instance of the "CAR" type that happens to be of interest, so there's no > particular reason to attach some modifying adjective that distinguishes > that instance from any other instance of the "CAR" type. This is by no > means a rare situation -- the above might be an argument to a method.) If it's the root of a tagged type hierarchy, then I would call it Root_Car, just like they do in the RM (example: Root_Storage_Pool). > Ada has only one namespace (within any given scope). Since Ada is also > case-insensitive, the only recourse is to come up with completely > different identifiers for a variable and for its type. This is indeed the case. Which is why I think it's confusing to use expanded name notation to differentiate between otherwise identical names for object and type. Use different identifiers for each. > It seems to me that if one is forced to come up with distinct > identifiers for a type and an (arbitrary) instance of that type, then > the difference between the identifiers should reflect this base/meta > distinction. Thus, the Cohen style: > > Car : Car_Type; Sometimes, if there really is no suitable adjective to describe the type (or, you're just not feeling too creative that day), then you do have to use _Type as the type name. But I find those times to be rare. > The old Booch style: > > The_Car : Car; > > also reflects this same base/meta distinction. I don't like this convention because it adds noise that the human reader is going to mentally parse out anyway, so why not parse it out for him? Better to name the type Car_Type, and the instance Car, becuase the object is going to be refered to more often than the type itself. > Matthew, you seem to be advocating a variation on the "abbreviation" > approach: Come up with some wordy phrase for a type name, and then > arbitrarily lop off some part of that phrase to come up with a variable > name. That seems ad hoc to me. I wouldn't call it ad hoc. You don't come up with a "wordy" phrase for the type name _arbitrarily_. Just the opposite is true: you come up with an adjective that applies to your abstraction. A new member of the team I'm on declared a bunch of types (it was a binding to a tape drive API) all using the _T convention. I pointed out to him that perhaps a better name would be to include the tape drive in the type name, instead of using _T. His rebuttal was to ask me how I'd name a color type. My immediate response is, "Well, what is it a color of?" He said, "Say, a car." So my advice was, name the type Car_Color, not Color_Type. Nor is the object name ad hoc: simply remove the adjective part of the name, and keep the noun part. Just like Mode is an instance of type File_Mode, or File is an instance of File_Type, or Pool is an instance of Static_Storage_Pool. Another simple example: I like to name all scalar types with a dimension by using the units in the name, as in Speed : Speed_In_MPH; Length : Length_In_Meters; This solves the object-name type-name issue, and removes any ambiguity about what units apply to the scalar type. When refering to a literal, I like to use a qualified name, as in Set_Speed (Car, Speed => Speed_In_MPH'(10.0)); to let the reader know that I really knew I was doing, setting the speed to a value with units in miles per hour. (It would also help if you needed to change the units for some reason; the compiler would complain about a now non-existent type.) > If it was important enough to say, in a type name, that something is a > "Car_Steering_Wheel" (as opposed to, perhaps, a "Truck_Steering_Wheel"), > then why isn't it also important to say "Car_Steering_Wheel" in the > variable name too? Why arbitrarily lop off the "Car_" part? Because you only need to tell me once about the nature of the abstraction. We all know, by reading the _entire_ declaration (not just the object name), that we're talking about the steering wheel of a car. It _is_ important to tell my that this is a car steering wheel, but you only need to tell me once (at declaration time), not tell me again and again and again every time I refer to the object. Because then it would just become information the reader is going to mentally parse out. So when I see an object called Mode, I know that this is a File_Mode, because I read the subprogram from top to bottom, starting with the declarative region, and noticed the declaration of object Mode. Had I started reading in the middle of the subprogram, and see object Mode, I simply scan the program text backwards until I find the declaration. (And if I have too scan far back, then the subprogram is probably too long.) > On the other hand, if the "Car_" part is already understood (because the > type is already nested inside a "Cars" package), then why bother with > the "Car_" part in the first place, in the type name? Isn't that just > noise? The Car_ part is there because we need to have a different name for the type, because we want to call the object Steering_Wheel. To use _Type really would be noise, because that doesn't tell me anything I don't already know (even though it does satisfy the need to use a different identifier for the type). If we know that the object is going to be called Steering_Wheel, and that we need a different (and longer) name for the type, then you might as well add additional, substantive information about the abstraction the type describes. (Note that I'm proceeding here under that assumption that types don't just float around in space; they're there for a reason, and steering wheel abstractions "go with" car abstractions. As they say, "No object is an island.") > If the type name were only "Steering_Wheel", what would you propose > lopping off from that to make the variable name? The "Steering_" part? > Then why did we need to say "Steering_" in the type name? Isn't that > just noise too? Precisely why I wouldn't name the type just Steering_Wheel. Then the object name would be Wheel, and that name has too many other potential meanings. The object name Steering_Wheel is unambiguous. > On the other hand, what if the car doesn't just have a steering wheel, > but also has four drive wheels? Then don't we need to say > "Steering_Wheel" and "Drive_Wheel", not only in the type names but also > in the variable names too? What do we lop off where? You might decide on the convention that "Wheel" refers to drive wheels, and "Steering_Wheel" refers to steering wheels. Or, you could lengthen the type names. Name the type Drive_Wheel_Type if you don't care for Car_Drive_Wheel. > And what do you propose we lop off of the type name "Car" to make a > variable name? Alternatively, what "noise" word shall we tack onto the > type name so we can then lop it off? If we were manipulating a class-wide object, then the object name would be Car the type Root_Car, as in procedure Move (Car : in out Root_Car'Class); This class-wide operation ("template method" for readers of the GoF book) would dispatch primitive operations of types in the Root_Car class. > A naming convention should be systematic, mechanical, predictable and > transparent. That means that it should take NO THOUGHT to apply it, or > to interpret the results. Be careful not to assume that God decided that this is so. This description of a "good" naming convention is a choice YOU made. In fact, I take the exact opposite position, and think that type names require careful consideration of the application, the nature of the abstraction, and of the intended names of instances. Yes, this sometimes requires thinking (gasp!) and a certain amount of creativity. This is our real disagreement. Clearly, you and I are arguing using a different set of axioms. No substantive debate can occur unless all parties agree on first principles. > The argument that this limits a programmer's creativity is specious. I'm not suggested that mechanical application of a naming convention limits a programmer's creativity. In fact, the convention I advocate often can be applied mechanically. > But I am at a loss to see how Heaney style would meet these criteria > in the most general case. Please don't call this the Heaney style - call it the RM style. My argument isn't for a naming convention per se, it's that we should stick to the conventions already being used in the language reference manual. (But, like reading the Bible or the US Constitution, those conventions are sometimes subject to interpretation, and aren't guaranteed to work for anything but what's required to write a reference manual!)