From: "John G. Volan" <johnvolan@sprintmail.com>
Subject: Re: Naming of Tagged Types and Associated Packages
Date: 1998/09/05
Date: 1998-09-05T00:00:00+00:00 [thread overview]
Message-ID: <35F15C7D.A33C272E@sprintmail.com> (raw)
In-Reply-To: m367f9rhdj.fsf@mheaney.ni.net
[Cross-posted to comp.lang.eiffel, since I've added Eiffel content]
Matthew Heaney wrote:
>
> "John G. Volan" <johnvolan@sprintmail.com> writes:
>
[...snip...]
> 3) Name scalar types using the units in the name, ie
>
> type Heading_In_Degrees is ...;
[...snip...]
> > As I've pointed out in the past, if it's important to say something in
> > a type name, there could easily be a case where it's important to say
> > it in the variable name too:
> >
> > Speed_In_MPH : Speed_In_MPH_Type;
> > Speed_In_Knots : Speed_In_Knots_Type;
> > ...
> > Speed_In_Knots := To_Knots(Speed_In_MPH);
>
> See my point above.
>
> The times when I care about the specific units of speed are only a
> subset of all the times I manipulate a speed. When I really do care
> about the units, I just navigate to the declaration, the read units from
> the type name.
>
> You don't need to tell me the units every single time, because I don't
> care about units every single time. And when I don't care, I have to
> mentally parse it out.
I'm not saying that such details need to be stated at _all_ times. I can
accept dropping prefixes and suffixes if the context allows, e.g.:
type Ship_Type is
record
Speed : Speed_In_Knots_Type;
...
end record;
Ship : Ship_Type;
... Ship.Speed ... -- we can look up the declaration to remind us of
-- the units
I'm merely saying that these suffixes and prefixes may be needed at
_some_ time, when the context forces us to disambiguate things, as in my
example you quoted above.
If you had to do the above conversion using your naming scheme, how
would you declare the two different "speed" objects? You rely on being
able to drop a
unit suffix to generate a variable name distinct from the type name. But
in the above situation, these suffixes are needed again to disambiguate
the two variables, which otherwise would have wound up with the same
name according to your scheme.
If your answer is, "Well, I'll just come up with some abbreviations for
the speed in knots variable vs. the speed in mph variable," then I'd
say, okay, you're free to do so, but then you'd have to admit that you
were doing something ad-hoc.
Remember, the reason we're forced into all these contortions is because
of Ada's case insensitivity, combined with its strict insistence that
type names and variable names share a single namespace (within a given
scope). In a language that relaxes either of these properties, we don't
have a problem. For instance, in Eiffel we might have:
expanded class SPEED_IN_MPH inherit DOUBLE feature ... end
expanded class SPEED_IN_KPH inherit DOUBLE feature ... end
expanded class SPEED_IN_KNOTS inherit DOUBLE feature ... end
class SHIP feature
speed: SPEED_IN_KNOTS
...
end -- class SHIP
And the above conversion situation would be something like:
speed_in_mph: SPEED_IN_MPH;
speed_in_knots: SPEED_IN_KNOTS;
...
speed_in_knots := to_knots (speed_in_mph)
> > Or perhaps we should consider the word "Speed" to be unnecessary noise:
> >
> > MPH : MPH_Type;
> > Knots : Knots_Type;
> > ...
> > Knots := To_Knots(MPH);
> > ...
> > Set_Speed (Car, MPH => 10.0);
> >
> > Perhaps "Speed" could be the name of the package that houses the
> > MPH_Type and Knots_Type, and the To_Knots function, etc...
>
> I don't like this idea. The characteristics of the supporting type,
> such as whether it's fixed or float, the digits of precision, range,
> etc, are determined by the larger abstraction. So I usually place the
> attribute types there, with the abstraction they describe.
If I'm reading this right, what you're saying is that if an analysis of
the problem domain indicates that a car has a speed in miles per hour,
you'd put a Car_Speed_In_MPH type in the Cars package along with a
<Something>_Car type?
Suppose further analysis of the problem domain indicated that weather
conditions constituted an important abstraction (let's say the system
does fine engine and transmission control to improve traction and fuel
economy in adverse weather). Then you might have a Wind_Speed_In_MPH
type in a Weather package.
Would these two speed types have no commonality? Would you be forced to
do a lot of type-conversions to work with them both? Why couldn't you
just have a single Speed_In_MPH_Type in a common package (regarding
Speeds) that could be shared between the Cars package and the Weather package?
I've often noted that Ada projects tend to proliferate a lot of
unnecessary, redundant representations for the same classes of physical
quantities. Little attempt is made to standardize on a normalized set
of unit types and accuracies, so you wind up with a lot of complex,
redundant, and hard to maintain conversion code scattered all over the
system.
Such projects might have benefited greatly if physical quantity types
had been treated as first-class abstractions in their own right, e.g.:
package Speeds is
type Speed_Type is private;
function From_MPH (MPH : in Long_Float) return Speed_Type;
function From_KPH (KPH : in Long_Float) return Speed_Type;
function From_Knots (Knots : in Long_Float) return Speed_Type;
...
function To_MPH (Speed : in Speed_Type) return Long_Float;
function To_KPH (Speed : in Speed_Type) return Long_Float;
function To_Knots (Speed : in Speed_Type) return Long_Float;
...
private
type Speed_Type is
record
MPH : Long_Float;
-- arbitrary choice, might be changed
-- without affecting the abstraction
end record;
end Speeds;
with Speed_Constants; use Speed_Constants;
package body Speeds is
function From_MPH (MPH : in Long_Float) return Speed_Type is
begin
return (MPH => MPH);
end From_MPH;
function From_KPH (KPH : in Long_Float) return Speed_Type is
begin
return (MPH => KPH * KPH_To_MPH);
end From_KPH;
function From_Knots (Knots : in Long_Float) return Speed_Type is
begin
return (MPH => Knots * Knots_To_MPH);
end From_Knots;
...
function To_MPH (Speed : in Speed_Type) return Long_Float is
begin
return Speed.MPH;
end To_MPH;
function To_KPH (Speed : in Speed_Type) return Long_Float is
begin
return Speed.MPH * MPH_To_KPH;
end To_KPH;
function To_Knots (Speed : in Speed_Type) return Long_Float is
begin
return Speed.MPH * MPH_To_Knots;
end To_Knots;
...
end Speed;
Here's a similar rendition in Eiffel:
expanded class
SPEED
inherit
SPEED_CONSTANTS;
-- assume provides Mph_to_kph, Kph_to_mph, etc...
DOUBLE_APPROXIMATION
-- assume provides comparison functions that account
-- for numeric inprecision in DOUBLE computations, e.g.:
-- sufficiently_equal, sufficiently_greater, etc.
-- Are such functions already available somewhere?
feature
mph: DOUBLE
-- this happens to be the only attribute,
-- but that is an arbitrary choice. The rest
-- are conversion functions:
kph: DOUBLE is
do
Result := mph * Mph_to_kph
end
knots: DOUBLE is
do
Result := mph * Mph_to_knots
end
...
set_mph (new_mph: DOUBLE) is
do
mph := new_mph
ensure
sufficiently_equal (mph, new_mph)
end
set_kph (new_kph: DOUBLE) is
do
mph := new_kph * Kph_to_mph
ensure
sufficiently_equal (kph, new_kph)
end
set_knots (new_knots: DOUBLE) is
do
mph := new_knots * Knots_to_mph
ensure
sufficiently_equal (knots, new_knots)
end
accelerate (delta_speed: SPEED) is
do
mph := mph + delta_speed.mph
ensure
sufficiently_equal (mph, mph + delta_speed.mph)
end
...
invariant
kph_definition:
sufficiently_equal (mph * Mph_to_kph, kph);
knots_definition:
sufficiently_equal (mph * Mph_to_knots, knots);
...
end -- class SPEED
An intriguing alternative possibility would be to make SPEED a deferred
class instead (an abstract type in Ada95 parlance):
deferred class
SPEED
inherit
SPEED_CONSTANTS;
-- assume provides Mph_to_kph, Kph_to_mph, etc...
DOUBLE_APPROXIMATION
-- assume provides comparison functions that account
-- for numeric inprecision in DOUBLE computations, e.g.:
-- sufficiently_equal, sufficiently_greater, etc.
-- Are such functions already available somewhere?
feature
mph: DOUBLE is deferred end
kph: DOUBLE is deferred end
knots: DOUBLE is deferred end
...
set_mph (new_mph: DOUBLE) is
deferred
ensure
sufficiently_equal (mph, new_mph)
end
set_kph (new_kph: DOUBLE) is
deferred
ensure
sufficiently_equal (kph, new_kph)
end
set_knots (new_knots: DOUBLE) is
deferred
ensure
sufficiently_equal (knots, new_knots)
end
accelerate (delta_speed: SPEED) is
require
delta_speed_exists: delta_speed /= Void
deferred
ensure
sufficiently_equal (mph, mph + delta_speed.mph)
end
...
invariant
kph_definition:
sufficiently_equal (mph * Mph_to_kph, kph);
knots_definition:
sufficiently_equal (mph * Mph_to_knots, knots);
...
end -- class SPEED
Then, you could have different heirs of this class optimized for
specific units of measure:
expanded class
SPEED_IN_MPH
inherit
SPEED
feature
mph: DOUBLE
kph: DOUBLE is
do
Result := mph * Mph_to_kph
end
knots: DOUBLE is
do
Result := mph * Mph_to_knots
end
...
accelerate (delta_speed: SPEED) is
do
mph := mph + delta_speed.mph
end
...
end -- class SPEED_IN_MPH
expanded class
SPEED_IN_KPH
inherit
SPEED
feature
mph: DOUBLE is
do
Result := kph * Kph_to_mph
end
kph: DOUBLE
knots: DOUBLE is
do
Result := kph * Kph_to_knots
end
...
accelerate (delta_speed: SPEED) is
do
kph := kph + delta_speed.kph
end
...
end -- end class SPEED_IN_KPH
... similarly for SPEED_IN_KNOTS, etc.
Then a class like CAR could have a SPEED attribute that could avail
itself of polymorphism:
class CAR creation
make
feature -- Status report
speed: SPEED
feature -- Status setting
set_speed (new_speed: SPEED) is
require
speed_exists: new_speed /= Void
do
speed := new_speed;
end
...
feature {NONE} -- Initialization
make is
do
...
!SPEED_IN_MPH! speed
-- default to optimize on miles per hour,
-- but can be changed later (via set_speed)
-- to optimize on other units
...
end
...
invariant
speed_exists: speed /= Void
...
end -- class CAR
--
indexing
description: "Signatures for John G. Volan"
self_plug: "Ex Ada guru", "Java 1.1 Certified", "Eiffelist wannabe"
two_cents: "Java would be even cooler with Eiffel's assertions/DBC, %
%generics, true MI, feature adaptation, uniform access, %
%selective export, expanded types, etc., etc..."
class JOHN_VOLAN_SIGNATURE inherit SIGNATURE invariant
disclaimer: not (opinion implies employer.opinion)
end -- class JOHN_VOLAN_SIGNATURE
next prev parent reply other threads:[~1998-09-05 0:00 UTC|newest]
Thread overview: 138+ messages / expand[flat|nested] mbox.gz Atom feed top
1998-07-16 0:00 Naming of Tagged Types and Associated Packages taashlo
1998-07-25 0:00 ` Matthew Heaney
1998-07-25 0:00 ` Jean-Pierre Rosen
1998-07-25 0:00 ` Brian Rogoff
1998-07-26 0:00 ` Matthew Heaney
1998-07-26 0:00 ` Matthew Heaney
1998-07-26 0:00 ` nabbasi
1998-07-26 0:00 ` Matthew Heaney
1998-07-26 0:00 ` Robert Dewar
1998-07-27 0:00 ` Jean-Pierre Rosen
1998-07-28 0:00 ` Matthew Heaney
1998-07-28 0:00 ` Jean-Pierre Rosen
1998-07-28 0:00 ` dennison
1998-07-29 0:00 ` Jean-Pierre Rosen
1998-07-29 0:00 ` dennison
1998-07-29 0:00 ` Jean-Pierre Rosen
1998-07-30 0:00 ` dennison
1998-07-30 0:00 ` Jean-Pierre Rosen
1998-07-29 0:00 ` Robert I. Eachus
1998-07-30 0:00 ` Matthew Heaney
1998-07-30 0:00 ` Jean-Pierre Rosen
1998-07-30 0:00 ` Robert I. Eachus
1998-07-31 0:00 ` Jean-Pierre Rosen
1998-07-31 0:00 ` Robert I. Eachus
1998-08-01 0:00 ` Jean-Pierre Rosen
1998-08-04 0:00 ` Matthew Heaney
1998-08-04 0:00 ` Jean-Pierre Rosen
1998-08-10 0:00 ` Robert I. Eachus
1998-07-27 0:00 ` dennison
1998-07-27 0:00 ` Stephen Leake
1998-07-27 0:00 ` dennison
1998-07-27 0:00 ` Brian Rogoff
1998-07-28 0:00 ` dennison
1998-07-28 0:00 ` Brian Rogoff
1998-07-28 0:00 ` dennison
1998-07-29 0:00 ` Matthew Heaney
1998-07-29 0:00 ` Chris Brand
1998-07-30 0:00 ` Matthew Heaney
1998-07-30 0:00 ` dennison
1998-07-30 0:00 ` Matthew Heaney
1998-07-30 0:00 ` dennison
1998-08-01 0:00 ` Simon Wright
1998-08-02 0:00 ` Matthew Heaney
1998-08-03 0:00 ` dennison
1998-08-03 0:00 ` Matthew Heaney
1998-08-04 0:00 ` dennison
1998-08-04 0:00 ` Jean-Pierre Rosen
1998-08-04 0:00 ` Brian Rogoff
1998-08-05 0:00 ` Don Harrison
1998-08-05 0:00 ` Matthew Heaney
1998-08-07 0:00 ` Don Harrison
1998-08-13 0:00 ` Robert A Duff
1998-08-14 0:00 ` Don Harrison
1998-08-14 0:00 ` adam
1998-08-05 0:00 ` Brian Rogoff
1998-08-07 0:00 ` Don Harrison
1998-08-07 0:00 ` doylep
1998-08-07 0:00 ` Brian Rogoff
1998-08-08 0:00 ` Matthew Heaney
1998-08-10 0:00 ` doylep
1998-08-10 0:00 ` Brian Rogoff
1998-08-10 0:00 ` John Volan
1998-08-10 0:00 ` John Volan
1998-08-11 0:00 ` doylep
1998-08-11 0:00 ` Brian Rogoff
1998-08-13 0:00 ` Robert A Duff
1998-08-13 0:00 ` Brian Rogoff
1998-09-01 0:00 ` Matthew Heaney
1998-09-01 0:00 ` Dale Stanbrough
1998-09-01 0:00 ` Matthew Heaney
1998-09-01 0:00 ` Bob Collins
1998-09-02 0:00 ` Matthew Heaney
1998-09-04 0:00 ` John G. Volan
1998-08-11 0:00 ` Don Harrison
1998-08-11 0:00 ` Pat Rogers
1998-08-11 0:00 ` Don Harrison
1998-09-01 0:00 ` Matthew Heaney
1998-08-13 0:00 ` Robert A Duff
1998-08-13 0:00 ` Brian Rogoff
1998-08-15 0:00 ` Don Harrison
1998-08-15 0:00 ` Jean-Pierre Rosen
1998-08-18 0:00 ` Don Harrison
1998-08-14 0:00 ` Don Harrison
1998-08-17 0:00 ` doylep
1998-08-19 0:00 ` Don Harrison
1998-08-12 0:00 ` Don Harrison
1998-08-08 0:00 ` Matthew Heaney
1998-08-08 0:00 ` John G. Volan
1998-08-09 0:00 ` Matthew Heaney
1998-08-10 0:00 ` John G. Volan
1998-08-11 0:00 ` John Volan
1998-08-11 0:00 ` Don Harrison
1998-08-11 0:00 ` geoff
1998-08-31 0:00 ` Matthew Heaney
1998-08-31 0:00 ` Tucker Taft
1998-09-06 0:00 ` John G. Volan
1998-09-06 0:00 ` Matthew Heaney
1998-09-04 0:00 ` John G. Volan
1998-09-05 0:00 ` Matthew Heaney
1998-09-05 0:00 ` John G. Volan
1998-09-04 0:00 ` John G. Volan
1998-09-05 0:00 ` John G. Volan
1998-09-06 0:00 ` Matthew Heaney
1998-09-06 0:00 ` Matthew Heaney
1998-09-04 0:00 ` John G. Volan
1998-09-06 0:00 ` Matthew Heaney
1998-09-06 0:00 ` John G. Volan
1998-09-06 0:00 ` John G. Volan
1998-09-06 0:00 ` Brian Rogoff
1998-09-06 0:00 ` John G. Volan
1998-09-07 0:00 ` Brian Rogoff
1998-09-07 0:00 ` John G. Volan
1998-09-16 0:00 ` Matthew Heaney
1998-09-05 0:00 ` John G. Volan [this message]
1998-09-05 0:00 ` John G. Volan
1998-08-11 0:00 ` doylep
1998-08-05 0:00 ` Static Polymorphism (Was Re: Naming of Tagged Types...) Brian Rogoff
1998-08-06 0:00 ` Matthew Heaney
1998-08-06 0:00 ` Brian Rogoff
1998-07-28 0:00 ` Naming of Tagged Types and Associated Packages Brian Rogoff
1998-07-29 0:00 ` Matthew Heaney
1998-07-29 0:00 ` Brian Rogoff
1998-07-28 0:00 ` Norman H. Cohen
1998-07-28 0:00 ` Stephen Leake
1998-07-28 0:00 ` Matthew Heaney
1998-07-28 0:00 ` Matthew Heaney
1998-07-28 0:00 ` Jean-Pierre Rosen
1998-07-28 0:00 ` Matthew Heaney
1998-07-28 0:00 ` dennison
1998-07-29 0:00 ` Matthew Heaney
1998-07-30 0:00 ` Robert Dewar
1998-07-30 0:00 ` Matthew Heaney
1998-08-06 0:00 ` Robert A Duff
1998-08-06 0:00 ` Matthew Heaney
1998-08-06 0:00 ` Tucker Taft
1998-08-31 0:00 ` Matthew Heaney
-- strict thread matches above, loose matches on Subject: below --
1998-07-26 0:00 tmoran
1998-07-27 0:00 ` dennison
replies disabled
This is a public inbox, see mirroring instructions
for how to clone and mirror all data and code used for this inbox