comp.lang.ada
 help / color / mirror / Atom feed
From: "John G. Volan" <johnvolan@sprintmail.com>
Subject: Re: Naming of Tagged Types and Associated Packages
Date: 1998/08/10
Date: 1998-08-10T00:00:00+00:00	[thread overview]
Message-ID: <35CEBAAF.B9B82820@sprintmail.com> (raw)
In-Reply-To: m3d8abkuv6.fsf@mheaney.ni.net

Matthew Heaney wrote:
> 
> "John G. Volan" <johnvolan@sprintmail.com> writes:
> 
> > (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).

Yes, this is an interesting idiom, and one may compare Ada's scheme of
grouping cohesive types within Ada packages with Java's scheme of
grouping cohesive classes within Java packages, or with Eiffel's scheme
of grouping cohesive classes within clusters using the Lace language.

However, this is off on a tangent from P. Doyle's question. P.D.'s
question (and mine) was essentially this:

You have a simple concept for some class of entities within your problem
domain, and you have come up with a short, pithy noun phrase (e.g.,
"CAR", "STEERING_WHEEL") that names this concept within the context of
your problem domain.  Let us assume that the verbiage in this noun
phrase is no more and no less than what is needed to convey the entire
problem-domain concept you have in mind; in other words, the component
words are at once necessary and sufficient. If that assumption is true,
then removing any words would yield an abbreviation, which is
insufficient; adding any words would create noise, which is unnecessary.
 Even words that convey the context of the problem domain are
unnecessary, since such context can either be assumed, or expressed as
module (package) names.

All things being equal, this necessary-and-sufficient noun phrase is
desirable both as an identifier for a type, and as an identifier for an
(arbitrary) variable of that type.  Every programming language requires
some mechanism for distinguishing such identifiers from each other. 
Ada's mechanism is to force the identifiers to be literally different,
which means either adding some kind of noise word to one or the other,
or resorting to abbreviation for one or the other. Many react with
distaste to either prospect, because they recognize both as catering to
the programming language, and not to the problem domain concept we are
trying to express. (Remember, the noun phrase in question is presumed to
be both necessary and sufficient to express the concept.)  Adding noise
seems less obnoxious than abbreviation. So what's the least obnoxious
noise you can add?

> > 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
...
> 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).

I hope you recognize that "Root_" is as much a noise word as any other,
because it caters to the mechanisms of the language rather than to the
problem domain.  Most OO programmers would find it distasteful to mark
the class at the top of an inheritance hierarchy this way, simply
because it was at the top of an inheritance hierarchy.

But this is another tangent irrelevant to P.D.'s simple question, and it
doesn't address the general case.  What if, for the particular problem
domain at hand, "CAR" is _not_ intended as the top of an inheritance
hierarchy?  In fact, what if we even wanted to _preclude_ any
inheritance?  (In Ada terms, the Car type would be non-tagged.  In Java,
it would be a final class.  In Eiffel ... not sure of the syntax.)  In
that case, attaching the "Root_" prefix would not only be noise, it
would be misleading noise.  So the question remains: All things being
equal, what's the least noxious noise you can add, that will work even
in the most general case?

> ... 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.

On this point, I agree.

> > 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.

Again, I take exception to the notion that it is "uncreative" to be
systematic. I'd rather focus my creativity on the terminology of the
problem domain and not waste it on irrelevant artefacts of the coding process.

But I find it interesting that you fall back to my position as a sort of
default: When all else fails, use the base/meta (object/type)
distinction as a source for the extra noise. But otherwise, be
"creative": Derive the noise, if you can, from some aspect of your
program design that's irrelevant to the problem domain (e.g. add "Root_"
to "Car"); or in other cases, redundantly express context that might
already be expressed in the module structure (e.g. add "Car_" to
"Steering_Wheel", even though it's already nested in a "Cars" package). 
What other cases do you propose?  With all these various cases, isn't
your scheme really ad hoc?  If you claim it is not ad hoc, can you
articulate a finite number of rules that cover all situations (or at
least a sufficient majority of them)?  The fewer rules the better,
because it means less effort for code writers to apply them, less effort
for code readers to determine which rule has been applied in a
particular situation, less effort for maintainers to keep straight what
they're talking about when they converse about the code, etc.

Personally, I find the form of "creativity" you advocate to be dubious. 
I know of no analog for your scheme in the idioms of any other
programming language.  Why not just settle on a simpler and more
systematic way to introduce the required noise, and have done with it? 
The base/meta distinction is always there, in every case. In fact, it is
the entire reason for this naming dilemma in the first place: We have
objects, and we have their types, and Ada requires that they have
different identifiers. So why not just have a single rule: Consistently
mark every type as such, and reserve the unmarked noun phrase for a
possible variable name.  It's how people speak about the code anyway:
"... and in this method we have an argument 'car' which is an instance
of the 'car' type, which we're using to ..."

> > 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?

But the whole point is that every scheme introduces noise. We are only
quibbling over which form of noise is the least distasteful.  I could as
easily say that the human reader is only interested that the thing is a
"Car", and will just parse out the "Root_" part anyway; or that the
thing is a "Steering_Wheel" from the "Cars" package, and will just parse
out the "Car_" part anyway; so why not just parse out these noise words
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.

Yes, I agree that there is a strong argument in favor of putting the
burden of marking upon the type identifier, in order to keep variable
names as short as possible.

However, when you add packages into this naming dilemma, it seems as if
a Booch-like style is still somewhat compelling, as J-P Rosen's style suggests:

  The_Car : Car.Instance;
  The_Steering_Wheel : Steering_Wheel.Instance;

Booch style gives the unmarked noun to the type; Rosen style gives it
instead to the package, and the encapsulated type gets a systematic
noise word.  It would have been nice if this word could have been just "Type":

  The_Car : Car.Type;
  The_Steering_Wheel : Steering_Wheel.Type;

but of course "type" is a reserved word.  (I once toyed with "Tipe", but
thought better of it ... :-)

> 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.

But you see, you diverted the poor guy off onto a tangent.  What if he
had responded, "Why, it's a color of anything that can _be_ colored, not
just the color of a car.  In short, "Color" is an abstraction all its
own, in a module of its own that is all about colors. Please don't
pollute that abstraction by making it specific to just one particular
usage... Now, this abstraction is about "Color" and only about "Color".
I want to call the package "Color".  But I also want to call the
encapsulated type "Color".  And I want to call the controlling parameter
"Color" in each of my primitve operations, too.  How do I resolve this dilemma?"

> 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, 

I don't think the original designers of Text_IO necessarily completely
thought through all the issues of naming conventions back then.  Isn't
the "File_" part in "File_Mode" just a redundant re-iteration of the
context, since we know that Text_IO is all about text files anyway?  (I
sometimes wish Text_IO had been named Text_Files instead, as this would
have been a more "object-oriented" name; "Text Input/Output" is the
_function_ this package supports, but "Text Files" are the _objects_
this package is _about_.)

On the other hand, let's suppose "File_Mode" is a necessary and
sufficient phrase to express the whole sense of the concept (presumably
within a use-ophilic environment).  Maybe you can get away with dropping
the "File_" adjective for a variable within the package, but can you
always do that outside the package, in all its conceivable clients? 
What if there's a context where you have both a "File_Mode" and some
other kind of mode, say an "Operational_Mode" (e.g., Real vs.
Simulated)?  Then it becomes important to use the complete names for
those concepts, including the "File_" and "Operational_" prefixes, not
just in their type names but also in the variable names.  If we now need
"File_Mode" and "Operational_Mode" as variable names, what should the
types have been called?

You know, I'm not averse to the idea, per se, of dropping prefixed
adjectives when they can be understood from the context.  In fact, in
object-oriented software, it's often the case that a subclass name will
be formed by prefixing an appropriate adjective onto its superclass
name.  A variable of the subclass type can just as easily be thought of
as a variable of the superclass type, so it can be legitimate to just
refer to the variable using the simpler terminology of the superclass type.

I'm just against the idea that dropping prefixed adjectives offers a
general solution to the object/type name dilemma.  One can always come
up with cases where you need to put those adjectives back in, or where
there are no appropriate adjectives to drop in the first place.

> 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.  

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);

> When refering to a literal,
> I like to use a qualified name, as in
> 
>    Set_Speed (Car, Speed => Speed_In_MPH'(10.0));

How about just:

     Set_Speed (Car, Speed_In_MPH => 10.0);

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...

> > 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.

Unless there's a situation where it becomes important again to
distinguish it as a car's steering wheel, and we find we need to put
that adjective back:

   Car_Steering_Wheel : Car_Steering_Wheel_Type := ...
   Tow_Truck_Steering_Wheel : Tow_Truck_Steering_Wheel_Type := ...
   ...
   -- make the Car simulation physically follow the Tow_Truck simulation:
   Set_Direction (Car_Steering_Wheel, Get_Direction (Tow_Truck_Steering_Wheel));

> > 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.

So basically you're saying the "Car_" part is just noise, right?

> 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).

But "Car_" doesn't tell me something I don't already know, either,
right?  I mean, to understand the entire abstraction, we don't just look
at a single _declaration_, we look at the whole _package_ that
encapsulates it, right?  The package name "Cars" already says it all.

> 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.

But what substantive information are you adding that hasn't already been
supplied in other ways?

   with Cars;  -- assume this is written by a use-o-phobe
   ...
      My_Cars_Steering_Wheel : Cars.Car_Steering_Wheel;
                               ^^^^^^^^

Isn't this redundant, and therefore noise?

> (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.")

Some objects are indeed islands, if we choose to keep them uncoupled to
other objects.  Making abstractions "go with" each other in a single
package increases coupling.  That's a design choice.  The benefits of
cohesion sometimes outweigh the cost of the coupling, but nevertheless
the coupling does incur a cost.  Sometimes the cost of coupling is too
dire, so the right design choice is to separate things out.

> > 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.

How is this the "opposite" of what I have been saying? Of course you
should take great care in choosing names that express the problem domain
_concepts_ you wish to address in your program.  There is a great deal
of care, consideration, and indeed creativity that goes into this design
process.  But once you have found names for your concepts, rendering
those concepts into types and variables should be as direct and
straightforward as possible.  If  your programming language forces you
to spend additional creative energy just to cater to its syntactic
foibles, that's a waste.  It would be as much of a waste to spend time
deciding what noise word to add, just for the sake of differentiating a
type name from variable name, as it is to spend time figuring out that:

  if (x = y) ...

really should have been:

  if (x == y) ...

> 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.

You seem to be contradicting yourself. How can your convention be
applied mechanically if by definition it requires creativity?  If your
convention can be expressed as a finite set of rules that cover all
situations, then by definition it would require no creativity (beyond
the initial creativity needed to give names to problem domain concepts,
of course).

> 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.

There appear to be many different conventions demonstrated within the
RM, possibly as many different styles as there were designers on the
design teams.  Perhaps the RM can be viewed as a forum where precedents
for various styles were recorded, but I don't think the intent of the RM
was ever to establish some particular coding style as the ideal. Its
primary intent, after all, was to unambiguously specify what the
language is, not to prescribe how it should be used.

Precedent, even long precedent, should not be the only criterion for
chosing a coding style. I would think it's more important to base the
choice on a well-thought out rationale.

As much as we venerate the wise men of ancient days, they really were no
closer to God than we are now.  But we have had more time to think about
it than they did.

-- 
Signature volanSignature =
  new Signature 
  ( /*name:      */ "John G. Volan",
    /*employer:  */ "Raytheon/TI Advanced C3I Systems, San Jose",
    /*workEmail: */ "johnv@ac3i.dseg.ti.com",
    /*homeEmail: */ "johnvolan@sprintmail.com",
    /*selfPlug:  */ "Sun Certified Java Programmer",
    /*twoCents:  */ "Java would be even cooler with Ada95's " +
                    "generics, named parameter passing, etc...",
    /*disclaimer:*/ "These views not packaged in COM.ti.dseg.ac3i.*, " +
                    "so loading them throws DontQuoteMeError. :-) " );




  reply	other threads:[~1998-08-10  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         ` Robert Dewar
1998-07-26  0:00         ` Matthew Heaney
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                                       ` adam
1998-08-14  0:00                                       ` Don Harrison
1998-08-05  0:00                                 ` Brian Rogoff
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 [this message]
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-06  0:00                                                 ` Matthew Heaney
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-06  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-05  0:00                                                 ` Matthew Heaney
1998-09-05  0:00                                                   ` John G. Volan
1998-09-05  0:00                                               ` John G. Volan
1998-09-05  0:00                                               ` John G. Volan
1998-08-11  0:00                                       ` doylep
1998-08-07  0:00                                   ` Don Harrison
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               ` Matthew Heaney
1998-07-28  0:00               ` Stephen Leake
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
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
  -- 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