comp.lang.ada
 help / color / mirror / Atom feed
* [SPARK] Code safety and information hiding
@ 2006-08-16  7:56 Maciej Sobczak
  2006-08-16  8:53 ` roderick.chapman
  2006-08-16 19:49 ` [SPARK] " Jeffrey R. Carter
  0 siblings, 2 replies; 34+ messages in thread
From: Maciej Sobczak @ 2006-08-16  7:56 UTC (permalink / raw)


Consider the following simple SPARK example:

package Random_Numbers is
   --# own Seed

   type Seed_Type is private;

   procedure Rand(X out Float);
   --# global Seed
   --# derives Seed from Seed & X from Seed;

private
   -- ...
end Random_Numbers;


The issue with this example is the apparent strong coupling between the 
specification of Rand (of the whole package, in fact) and the 
implementation details that pop up in specs in terms of the Seed name 
used in annotations.
It looks that the dependency between the body and spec is no longer 
one-way, as it logically should be, but the coupling is stronger - I 
cannot even change the name of the own Seed object, because it will 
force me to update the annotations in the specs; which in turn will 
force other packages (which should not depend on what name I use for 
Seed) that depend on these specs to recompile.

I don't find the above to be particularly disturbing, but I'm tempted to 
conclude that in SPARK increased code safety has the price of reduced 
information hiding, which itself was always considered to be a good 
engineering practice.

Your comments are welcome.

-- 
Maciej Sobczak : http://www.msobczak.com/
Programming    : http://www.msobczak.com/prog/



^ permalink raw reply	[flat|nested] 34+ messages in thread

* Re: Code safety and information hiding
  2006-08-16  7:56 [SPARK] Code safety and information hiding Maciej Sobczak
@ 2006-08-16  8:53 ` roderick.chapman
  2006-08-16 11:18   ` Stuart
  2006-08-16 19:49 ` [SPARK] " Jeffrey R. Carter
  1 sibling, 1 reply; 34+ messages in thread
From: roderick.chapman @ 2006-08-16  8:53 UTC (permalink / raw)


> The issue with this example is the apparent strong coupling between the
> specification of Rand (of the whole package, in fact) and the
> implementation details that pop up in specs in terms of the Seed name
> used in annotations.

SPARK promotes the hiding of _detail_, but not the hiding of
_information_.

The package spec you cite _does_ need to announce the existance of
"Seed" (but not its type, structure, or anything else).  You are also
correct
to identify that choosing the name "Seed" is crucial, since changing it
later
can have a non-trivial impact on clients of this package.

(Put another way - the abstraction offered by the package should be as
simple as it can be but no simpler (cf Occam's rule))

If you removed the announcement of "Seed" altogether, then the only
legal information flow relation for your PRNG would be

 --# derives X from ;

which (in information flow terms) means "The final value of X is a
constant" - not
a very good abstraction of a random number generator! :-)

 Yours,
  Rod Chapman, SPARK Team




^ permalink raw reply	[flat|nested] 34+ messages in thread

* Re: Code safety and information hiding
  2006-08-16  8:53 ` roderick.chapman
@ 2006-08-16 11:18   ` Stuart
  2006-08-16 13:23     ` Maciej Sobczak
  0 siblings, 1 reply; 34+ messages in thread
From: Stuart @ 2006-08-16 11:18 UTC (permalink / raw)


To follow up on what Rod has said in reply to:

"Maciej Sobczak" <no.spam@no.spam.com> wrote in message 
news:ebuj47$bal$1@sunnews.cern.ch...

<roderick.chapman@googlemail.com> wrote in message 
news:1155718392.684202.17080@p79g2000cwp.googlegroups.com...

>> The issue with this example is the apparent strong coupling between the
>> specification of Rand (of the whole package, in fact) and the
>> implementation details that pop up in specs in terms of the Seed name
>> used in annotations.
>
> SPARK promotes the hiding of _detail_, but not the hiding of
> _information_.
>
> The package spec you cite _does_ need to announce the existance of
> "Seed" (but not its type, structure, or anything else).  You are also
> correct to identify that choosing the name "Seed" is crucial, since
> changing it later can have a non-trivial impact on clients of this 
> package.

An important point identified by the SPARK annotation is that you have 
chosen to implement it as an Abstract State Machine (single instance shared 
by all clients), rather than an Abstract Data Type that can have multiple 
independent instances (with the Seed as a parameter).

As to the choice of name - I thought that SPARK's data refinement rules 
allowed you to change the view (effectively including the names used) 
between package specification and package body.

>> I don't find the above to be particularly disturbing, but I'm tempted to
>> conclude that in SPARK increased code safety has the price of reduced
>> information hiding, which itself was always considered to be a good
>> engineering practice.

Rod's distinction between detail and information is a good one.  It should 
also be remembered that the objective of SPARK is to allow you to reason 
about what your program will do.  Often, in less rigorous design processes, 
you might assume that a subprogram you use has no unexpected consequences 
(e.g. side-effects).  SPARK is much more rigorous - it makes sure that 
subprograms have no side-effects: the consequence is that _all_ effects of a 
subprogram must be recorded (e.g. updating the Seed in the Random number 
example).

Regards
-- 
Stuart Palin 





^ permalink raw reply	[flat|nested] 34+ messages in thread

* Re: Code safety and information hiding
  2006-08-16 11:18   ` Stuart
@ 2006-08-16 13:23     ` Maciej Sobczak
  0 siblings, 0 replies; 34+ messages in thread
From: Maciej Sobczak @ 2006-08-16 13:23 UTC (permalink / raw)


Stuart wrote:

> Rod's distinction between detail and information is a good one.  It should 
> also be remembered that the objective of SPARK is to allow you to reason 
> about what your program will do.  Often, in less rigorous design processes, 
> you might assume that a subprogram you use has no unexpected consequences 
> (e.g. side-effects).  SPARK is much more rigorous - it makes sure that 
> subprograms have no side-effects: the consequence is that _all_ effects of a 
> subprogram must be recorded (e.g. updating the Seed in the Random number 
> example).

I understand it. It's clear to me now that the spec should declare any 
interaction of the given subprogram with its environment and global 
variables are part of it - but it also became clear that with adding 
'global' annotations the network of known and checked dependencies is 
getting much denser. It's this density of dependencies that has struck 
me at the beginning.


-- 
Maciej Sobczak : http://www.msobczak.com/
Programming    : http://www.msobczak.com/prog/



^ permalink raw reply	[flat|nested] 34+ messages in thread

* Re: [SPARK] Code safety and information hiding
  2006-08-16  7:56 [SPARK] Code safety and information hiding Maciej Sobczak
  2006-08-16  8:53 ` roderick.chapman
@ 2006-08-16 19:49 ` Jeffrey R. Carter
  2006-08-17  7:01   ` Maciej Sobczak
  2006-08-18 23:02   ` Robert A Duff
  1 sibling, 2 replies; 34+ messages in thread
From: Jeffrey R. Carter @ 2006-08-16 19:49 UTC (permalink / raw)


Maciej Sobczak wrote:
> Consider the following simple SPARK example:
> 
> package Random_Numbers is --# own Seed

You need to terminate this with ';'.

> type Seed_Type is private;

This is never referenced, so may be removed.

> procedure Rand(X out Float); --# global Seed

This should probably be

--# global in out Seed;

> --# derives Seed from Seed & X from Seed;
> 
> private -- ...

No private part needed, since we've removed Seed_Type.

> end Random_Numbers;
> 
> The issue with this example is the apparent strong coupling between
> the specification of Rand (of the whole package, in fact) and the 
> implementation details that pop up in specs in terms of the Seed name
>  used in annotations.
> 
> It looks that the dependency between the body and spec is no longer 
> one-way, as it logically should be, but the coupling is stronger - I
>  cannot even change the name of the own Seed object, because it will
>  force me to update the annotations in the specs; which in turn will
>  force other packages (which should not depend on what name I use for
>  Seed) that depend on these specs to recompile.

No such coupling need exist. Suppose you decide during implementation
that the name of the state variable should really be Fred. This probably
means that you need to revisit the design decisions that lead to
choosing the name Seed, but maybe Seed is a good name for the clients of
the package, but not for the implementation. In that case, the body can
contain

--# own Seed is Fred;

The idea is that the spec contains the minimum information needed to 
reason formally about the behavior of the package. The existence and 
manipulation of the Seed is necessary for such reasoning.

[Aside: I really don't like the use of the term "global" for state 
variables. True global variables (in package specs) should be illegal; 
state variables are a different cup of fish and should not be tainted by 
the "global" label.]

-- 
Jeff Carter
"This trial is a travesty. It's a travesty of a mockery of a
sham of a mockery of a travesty of two mockeries of a sham. ...
Do you realize there's not a single homosexual on that jury?"
Bananas
27



^ permalink raw reply	[flat|nested] 34+ messages in thread

* Re: [SPARK] Code safety and information hiding
  2006-08-16 19:49 ` [SPARK] " Jeffrey R. Carter
@ 2006-08-17  7:01   ` Maciej Sobczak
  2006-08-17 18:08     ` Jeffrey R. Carter
  2006-08-18 23:02   ` Robert A Duff
  1 sibling, 1 reply; 34+ messages in thread
From: Maciej Sobczak @ 2006-08-17  7:01 UTC (permalink / raw)


Jeffrey R. Carter wrote:

>> type Seed_Type is private;
> 
> This is never referenced, so may be removed.

I specifically wrote '-- ...' in the private part to show that it has 
some content, but not relevant to the main point.

>> private -- ...
> 
> No private part needed, since we've removed Seed_Type.

The private part is needed to define Seed_Type, which was elided as not 
relevant.

But as I've said, it's not relevant. :-)

>> It looks that the dependency between the body and spec is no longer 
>> one-way, as it logically should be, but the coupling is stronger - I
>>  cannot even change the name of the own Seed object, because it will
>>  force me to update the annotations in the specs; which in turn will
>>  force other packages (which should not depend on what name I use for
>>  Seed) that depend on these specs to recompile.
> 
> No such coupling need exist. Suppose you decide during implementation
> that the name of the state variable should really be Fred. This probably
> means that you need to revisit the design decisions that lead to
> choosing the name Seed, but maybe Seed is a good name for the clients of
> the package, but not for the implementation. In that case, the body can
> contain
> 
> --# own Seed is Fred;

Interesting, but it looks that there is another solution to this: 
refinement. The specification only says that there is some State and the 
body clarifies what are the components of the State. This decouples the 
minor design decisions (like the choice of names in the implementation) 
from the clients, which then only need to know what affects the state - 
now treated in abstract terms - and what doesn't.


> [Aside: I really don't like the use of the term "global" for state 
> variables. True global variables (in package specs) should be illegal; 
> state variables are a different cup of fish and should not be tainted by 
> the "global" label.]

Agreed. Moreover, SPARK calls "global" even those variables, which are 
actually local in the scope that encloses the definition of the given 
subprogram. Intuitively, "globalness" of some name should not be a 
property of the place where the name is used.


-- 
Maciej Sobczak : http://www.msobczak.com/
Programming    : http://www.msobczak.com/prog/



^ permalink raw reply	[flat|nested] 34+ messages in thread

* Re: [SPARK] Code safety and information hiding
  2006-08-17  7:01   ` Maciej Sobczak
@ 2006-08-17 18:08     ` Jeffrey R. Carter
  2006-08-17 20:00       ` Björn Persson
  0 siblings, 1 reply; 34+ messages in thread
From: Jeffrey R. Carter @ 2006-08-17 18:08 UTC (permalink / raw)


Maciej Sobczak wrote:
> 
> Interesting, but it looks that there is another solution to this: 
> refinement. The specification only says that there is some State and the 
> body clarifies what are the components of the State. This decouples the 
> minor design decisions (like the choice of names in the implementation) 
> from the clients, which then only need to know what affects the state - 
> now treated in abstract terms - and what doesn't.

Right. That's what I was showing you, in its simplest version.

> Agreed. Moreover, SPARK calls "global" even those variables, which are 
> actually local in the scope that encloses the definition of the given 
> subprogram. Intuitively, "globalness" of some name should not be a 
> property of the place where the name is used.

Those are what I called state variables.

-- 
Jeff Carter
"I'm particularly glad that these lovely children were
here today to hear that speech. Not only was it authentic
frontier gibberish, it expressed a courage little seen
in this day and age."
Blazing Saddles
88



^ permalink raw reply	[flat|nested] 34+ messages in thread

* Re: [SPARK] Code safety and information hiding
  2006-08-17 18:08     ` Jeffrey R. Carter
@ 2006-08-17 20:00       ` Björn Persson
  2006-08-18  1:22         ` Jeffrey R. Carter
  0 siblings, 1 reply; 34+ messages in thread
From: Björn Persson @ 2006-08-17 20:00 UTC (permalink / raw)


Jeffrey R. Carter wrote:
> Maciej Sobczak wrote:
>> Agreed. Moreover, SPARK calls "global" even those variables, which are 
>> actually local in the scope that encloses the definition of the given 
>> subprogram. Intuitively, "globalness" of some name should not be a 
>> property of the place where the name is used.
> 
> Those are what I called state variables.

Do you call them state variables even when they're local in a subprogram 
and "global" only to a nested subprogram?

-- 
Bj�rn Persson                              PGP key A88682FD
                    omb jor ers @sv ge.
                    r o.b n.p son eri nu



^ permalink raw reply	[flat|nested] 34+ messages in thread

* Re: [SPARK] Code safety and information hiding
  2006-08-17 20:00       ` Björn Persson
@ 2006-08-18  1:22         ` Jeffrey R. Carter
  2006-08-18 19:39           ` Björn Persson
  0 siblings, 1 reply; 34+ messages in thread
From: Jeffrey R. Carter @ 2006-08-18  1:22 UTC (permalink / raw)


Bj�rn Persson wrote:
> 
> Do you call them state variables even when they're local in a subprogram 
> and "global" only to a nested subprogram?

Generally, no. State should usually be encapsulated in a package. In the 
context of SPARK's "own" and "global" annotations, state for a 
state-machine package is what I was discussing. There are cases where a 
main subprogram is essentially a state machine and simply calls 
subprograms that operate on the state, and I've hacked out a few of 
those in my day. In retrospect, though, a better and more thorough 
design, with better encapsulation of the state, would have been better.

Variables such as you discuss, though, don't generally have the negative 
effects of true global variables, found in library-level package specs. 
I've seen safety-critical SW designed around thousands of such variables 
in hundreds of packages, with absolutely no documentation. This results 
in maximal coupling and minimal cohesion. I find such SW very difficult 
to understand, and don't understand how it was ever certified.

-- 
Jeff Carter
"I'm particularly glad that these lovely children were
here today to hear that speech. Not only was it authentic
frontier gibberish, it expressed a courage little seen
in this day and age."
Blazing Saddles
88



^ permalink raw reply	[flat|nested] 34+ messages in thread

* Re: [SPARK] Code safety and information hiding
  2006-08-18  1:22         ` Jeffrey R. Carter
@ 2006-08-18 19:39           ` Björn Persson
  2006-08-19  5:35             ` Jeffrey R. Carter
  0 siblings, 1 reply; 34+ messages in thread
From: Björn Persson @ 2006-08-18 19:39 UTC (permalink / raw)


Jeffrey R. Carter skrev:
> Bj�rn Persson wrote:
>> Do you call them state variables even when they're local in a 
>> subprogram and "global" only to a nested subprogram?
> 
> Generally, no.

Do you think we could come up with a good word for them? They could be 
described as external to the nested subprogram, but if we'd call them 
"external variables" it would sound like they were declared as "extern" 
in C. How about "outer" or "outside" variables?

I agree with all of what you wrote by the way.

-- 
Bj�rn Persson                              PGP key A88682FD
                    omb jor ers @sv ge.
                    r o.b n.p son eri nu



^ permalink raw reply	[flat|nested] 34+ messages in thread

* Re: [SPARK] Code safety and information hiding
  2006-08-16 19:49 ` [SPARK] " Jeffrey R. Carter
  2006-08-17  7:01   ` Maciej Sobczak
@ 2006-08-18 23:02   ` Robert A Duff
  2006-08-19  5:40     ` Jeffrey R. Carter
  2006-08-23  9:44     ` Peter Amey
  1 sibling, 2 replies; 34+ messages in thread
From: Robert A Duff @ 2006-08-18 23:02 UTC (permalink / raw)


"Jeffrey R. Carter" <spam.not.jrcarter@acm.not.spam.org> writes:

> [Aside: I really don't like the use of the term "global" for state
> variables. True global variables (in package specs) should be illegal;
> state variables are a different cup of fish and should not be tainted by
> the "global" label.]

I think the terms "global" and "local" are most useful if they are
relative to something.  A variable can be more global or less global.
The Ada RM agrees with that (not surprising, since I wrote
that part ;-)).  See quote below.

Jeff wants to consider package-spec variables particularly evil.
OK, but there are global variables even more global than that.
The Registry in windows is an obnoxiously global variable.
And environment variables under many operating systems are
obnoxiously global.  I suppose disk files are global, although
I don't usually find them obnoxious.

I don't agree that package-spec variables should be illegal.  Such a
rule accomplishes nothing, since the programmer can just have a getter
and a setter, which is just as evil.  In some rare cases, a package-spec
variable makes sense, and in those cases, the getter/setter method is no
better (just more verbose).

So I like the SPARK syntax for "global".  It means so-and-so variable is
global to this procedure, not necessarily global to the whole program,
or global to that part of the program that with's certain package, or
global to the whole world.

AARM-8.1 says:

14    [{local to} A declaration is local to a declarative region if the
declaration occurs immediately within the declarative region.] [An entity is
local to a declarative region if the entity is declared by a declaration that
is local to the declarative region.]

    14.a  Ramification: "Occurs immediately within" and "local to" are
          synonyms (when referring to declarations).

    14.b  Thus, "local to" applies to both declarations and entities, whereas
          "occurs immediately within" only applies to declarations. We use
          this term only informally; for cases where precision is required, we
          use the term "occurs immediately within", since it is less likely to
          cause confusion.

15    {global to} A declaration is global to a declarative region if the
declaration occurs immediately within another declarative region that encloses
the declarative region. An entity is global to a declarative region if the
entity is declared by a declaration that is global to the declarative region.

- Bob



^ permalink raw reply	[flat|nested] 34+ messages in thread

* Re: [SPARK] Code safety and information hiding
  2006-08-18 19:39           ` Björn Persson
@ 2006-08-19  5:35             ` Jeffrey R. Carter
  2006-08-19 12:47               ` Björn Persson
  0 siblings, 1 reply; 34+ messages in thread
From: Jeffrey R. Carter @ 2006-08-19  5:35 UTC (permalink / raw)


Bj�rn Persson wrote:
> 
> Do you think we could come up with a good word for them? They could be 
> described as external to the nested subprogram, but if we'd call them 
> "external variables" it would sound like they were declared as "extern" 
> in C. How about "outer" or "outside" variables?

How about "non-local"?

-- 
Jeff Carter
"Apart from the sanitation, the medicine, education, wine,
public order, irrigation, roads, the fresh water system,
and public health, what have the Romans ever done for us?"
Monty Python's Life of Brian
80



^ permalink raw reply	[flat|nested] 34+ messages in thread

* Re: [SPARK] Code safety and information hiding
  2006-08-18 23:02   ` Robert A Duff
@ 2006-08-19  5:40     ` Jeffrey R. Carter
  2006-08-19  9:49       ` Stephen Leake
  2006-08-23  9:44     ` Peter Amey
  1 sibling, 1 reply; 34+ messages in thread
From: Jeffrey R. Carter @ 2006-08-19  5:40 UTC (permalink / raw)


Robert A Duff wrote:
> 
> I don't agree that package-spec variables should be illegal.  Such a
> rule accomplishes nothing, since the programmer can just have a getter
> and a setter, which is just as evil.  In some rare cases, a package-spec
> variable makes sense, and in those cases, the getter/setter method is no
> better (just more verbose).

Designs based around global (package spec) variables are clearly done by 
people who are not competent to be designing SW. Such people can always 
find others ways to create SW that's just as bad. But such a person 
might not immediately think in terms of getter/setter operations if 
denied the use of global variables, so not allowing them might provide a 
little pressure towards better designs.

The real solution, recognizing that all SW people are not equal, doesn't 
seem likely to happen any time soon.

-- 
Jeff Carter
"Apart from the sanitation, the medicine, education, wine,
public order, irrigation, roads, the fresh water system,
and public health, what have the Romans ever done for us?"
Monty Python's Life of Brian
80



^ permalink raw reply	[flat|nested] 34+ messages in thread

* Re: [SPARK] Code safety and information hiding
  2006-08-19  5:40     ` Jeffrey R. Carter
@ 2006-08-19  9:49       ` Stephen Leake
  2006-08-20  3:52         ` Jeffrey R. Carter
  0 siblings, 1 reply; 34+ messages in thread
From: Stephen Leake @ 2006-08-19  9:49 UTC (permalink / raw)


"Jeffrey R. Carter" <spam.not.jrcarter@acm.not.spam.org> writes:

> Robert A Duff wrote:
>> I don't agree that package-spec variables should be illegal.  Such a
>> rule accomplishes nothing, since the programmer can just have a getter
>> and a setter, which is just as evil.  In some rare cases, a package-spec
>> variable makes sense, and in those cases, the getter/setter method is no
>> better (just more verbose).
>
> Designs based around global (package spec) variables are clearly done
> by people who are not competent to be designing SW. 

I think I'll choose to take offense at this statement (it's 5:26 AM,
and I can't sleep because I've got a bit of the flu, so I claim the
right :).

I have an application called Goddard Dynamic Simulator (GDS); it is
used to test flight software and hardware for NASA Goddard (yes, I am
a rocket scientist). It has 90,000 lines of code, mostly Ada, some C
and VHDL.

The design uses information hiding, abstraction, etc; all the good
features of a good program, made easy by using Ada 2005.

However, there are some global variables. I thought long and hard
about each one, and decided they are the best solution to the problem.

One important global variable is the root of the symbol table. GDS
consists of many modules, that use the symbol table to communicate.
One module models a star tracker, another a spacecraft (which contains
the star tracker), another thrusters, etc. In addition, any symbol can
be written by the user, or displayed to the user.

This design has evolved thru several iterations of similar systems.
They all have a global symbol table.

In addition, there are global variables that indicate global
information about mode: 

   type Distribute_Mode_Type is (Master_Mode, Remote_Mode, Single_Mode);

   Distribute_Mode : Distribute_Mode_Type := Single_Mode;

this indicates whether GDS is running on a single computer, or on
several. This makes a difference in many places in the code.

   Ignore_Hardware_Errors : Boolean := False;
   --  Set True for unit tests when hardware is not present or should
   --  be ignored.

Unit tests are important, and this feature is the simplest way to
support running them without hardware, in a system that normally talks
to hardware.

   Main_Config : SAL.Config_Files.Configuration_Type;

More information that the entire system needs.


I claim to be competent to design SW; I have 20 years of experience,
and at least 10 monetary awards for outstanding performance, together
with high praise from my (internal) customers, to prove that. My
system has a few global variables because they are the right solution
to the problem.

> Such people can always find others ways to create SW that's just as
> bad. But such a person might not immediately think in terms of
> getter/setter operations if denied the use of global variables, so
> not allowing them might provide a little pressure towards better
> designs.

You have not said why getter/setter would be better for these
variables. I agree with Robert; they are just more verbose.

Hmm. You could try to impose control over what parts of the system are
"allowed" to write the variables, as opposed to reading them. But that
would require an elaborate system of IDs for various parts of the
system (which does not otherwise exist); definitely not worth it.

I'll make a counter claim; people who claim global variables are
_always_ bad should not be designing large complex systems; the
systems will be more complex than necessary, which is definitely a Bad
Thing.

> The real solution, recognizing that all SW people are not equal,
> doesn't seem likely to happen any time soon.

While it is true that all SW people are not equal, I don't see what
that has to do with the issue of global variables, nor do I see what
problem recognizing that might be a solution to.

-- 
-- Stephe



^ permalink raw reply	[flat|nested] 34+ messages in thread

* Re: [SPARK] Code safety and information hiding
  2006-08-19  5:35             ` Jeffrey R. Carter
@ 2006-08-19 12:47               ` Björn Persson
  2006-08-20  3:58                 ` Jeffrey R. Carter
  0 siblings, 1 reply; 34+ messages in thread
From: Björn Persson @ 2006-08-19 12:47 UTC (permalink / raw)


Jeffrey R. Carter wrote:
> How about "non-local"?

Well, maybe, but I think it sounds like the variable isn't local 
anywhere at all, which would mean it's global.

If possible I'd like to find a term that doesn't need to be redefined to 
mean something else than it normally means.

"Externally local" could work, but it's a bit unwieldy.

-- 
Bj�rn Persson                              PGP key A88682FD
                    omb jor ers @sv ge.
                    r o.b n.p son eri nu



^ permalink raw reply	[flat|nested] 34+ messages in thread

* Re: [SPARK] Code safety and information hiding
  2006-08-19  9:49       ` Stephen Leake
@ 2006-08-20  3:52         ` Jeffrey R. Carter
  2006-08-20 19:06           ` Stephen Leake
  0 siblings, 1 reply; 34+ messages in thread
From: Jeffrey R. Carter @ 2006-08-20  3:52 UTC (permalink / raw)


Stephen Leake wrote:
> 
> I think I'll choose to take offense at this statement (it's 5:26 AM, 
> and I can't sleep because I've got a bit of the flu, so I claim the 
> right :).

I have a bad cold, and did when I wrote the statement to which you're
responding, so I claim the right to argue back. Let's spray our addled 
perceptions into c.l.a, where someone will reference them as definitive 
in the future.

> I have an application called Goddard Dynamic Simulator (GDS); it is 
> used to test flight software and hardware for NASA Goddard (yes, I am
>  a rocket scientist). It has 90,000 lines of code, mostly Ada, some C
>  and VHDL.

I've never been sure what a "rocket scientist" is. Is it someone who 
deals with the theory of anaerobic propulsion systems? Or is it a more 
general science dealing with launch systems overall?

In any case, being a scientist is probably not a qualification for
designing actual systems. Scientists deal with theory; engineers with
creating systems. Physicists are not necessarily competent to design 
bridges; civil engineers are.

> However, there are some global variables. I thought long and hard 
> about each one, and decided they are the best solution to the
> problem.

Some is probably better than lots. With "some" they might be well
documented. As I've said, I've seen large, safety-critical systems
designed around thousands of undocumented global variables. I think it
would be faster and easier to redesign and reimplement these systems
than to understand them well enough to safely make changes to a small
part of them.

I've often had similar thoughts about systems in which simple boolean 
options exist which may be changed at any time. If it's a sequential 
system, Boolean variables seem sufficient. For a concurrent system, 
making them atomic should be enough, though I would prefer a protected 
object. On the other hand, I don't want to seem to give permission for 
modifiers of the system to create global variables that are more complex 
or have more restricted situations when they may be accessed.

> This design has evolved thru several iterations of similar systems. 
> They all have a global symbol table.

So, as a modifier of the system, without reading and understanding all
parts of the system that may access this variable, it's OK for me to 
write to this variable whenever it's convenient?

> type Distribute_Mode_Type is (Master_Mode, Remote_Mode, Single_Mode);
> 
> Distribute_Mode : Distribute_Mode_Type := Single_Mode;

Again, it must be reasonable and meaningful for me to change the SW to 
write this variable whenever it suits me.

If that's not the case, then I claim this should not be a variable. 
Instead of being able to write

X.Distribute_Mode := X.Master_Mode;

I should have to call something like

function Request_Distribute_Mode_Change
    (New_Mode : Distribute_Mode_Type)
return Boolean;
-- Request mode change to New_Mode.
-- Returns True if the mode change is legal; False otherwise.

All the details of when a mode change may occur should be encapsulated 
with the current mode value.

On the 3rd hand, systems generally are either distributed or not, and 
that doesn't change during execution. In that case, this is essentially 
a constant. If the actual mode is determined at run time during start 
up, then probably the value should be encapsulated with the logic that 
determines it, and the resulting value be made available to the rest of 
the system through a function.

In this latter case, there may also be a race condition. What if one 
part of the system reads this and gets the default value before its 
actual value is determined? It's probably better to control that locally 
than otherwise.

>    Ignore_Hardware_Errors : Boolean := False;
>    --  Set True for unit tests when hardware is not present or should
>    --  be ignored.

Shouldn't that be "Boolean_Type"?

This is documented, and shows that it isn't a variable. Clearly this 
should have the same value for an entire execution; I've never seen SW 
that switches between unit test and other modes during execution. I 
suspect your SW would be clearer if this were a constant.

> I claim to be competent to design SW; I have 20 years of experience, 
> and at least 10 monetary awards for outstanding performance, together
>  with high praise from my (internal) customers, to prove that. My 
> system has a few global variables because they are the right solution
>  to the problem.

Perhaps. Who modifies the system? Add 1 undocumented global variable to 
a system, and you generally increase the coupling and decrease the 
cohesion. You understand the system, but after you're hit by a truck, 
how easy is it for someone who doesn't have any experience with the 
system to figure out how it works?

> You have not said why getter/setter would be better for these 
> variables. I agree with Robert; they are just more verbose.

I don't think they're better. I said that if global variables were not 
available, those who would try to base their designs around them might 
not think of using such operations to mimic them.

> Hmm. You could try to impose control over what parts of the system
> are "allowed" to write the variables, as opposed to reading them. But
> that would require an elaborate system of IDs for various parts of
> the system (which does not otherwise exist); definitely not worth it.

You might simply document who may write and who may read such variables. 
That would be a big improvement in the global-centric systems I've seen. 
Of course, that goes against the basic Ada philosophy that packages 
should not be concerned with who their clients are. That's something 
that's not always achievable in large, real SW systems. There are 
sometimes operations that are documented as "used only by X and Y to 
achieve Z". Such things should generally be private to some subsystem.

In general, values should be encapsulated with the logic that generates 
or modifies them, and systems that are designed that way have better 
coupling and cohesion than systems that aren't. Systems designed around 
global variables are an extreme example of the latter. If your SW 
determines a value in one place and stores it in another, that's an 
indication that you may need to rethink your design. If the value is 
determined in multiple places, that's almost always a red flag.

Now, I've worked on systems with physical redundancy, so that one 
processor is the currently active one, and the others shadow it and are 
prepared to take over if it fails. I've worked on such systems where the 
determination of which is the active processor is made by another part 
of the system, so it is necessary to distribute that value to the 
processors. In that case, the SW pretends that it determines the value; 
for example, there's a module that encapsulates the value and provides 
access to it to other parts of the SW. There isn't a procedure Set for 
the value; rather, the module has an operation that receives and 
processes the message that changes the value.

> I'll make a counter claim; people who claim global variables are 
> _always_ bad should not be designing large complex systems; the 
> systems will be more complex than necessary, which is definitely a
> Bad Thing.

I have over 30 yrs of professional SW development experience, and I 
still find myself doing things I know I shouldn't. Hopefully I catch 
them most of the time in the important cases. But I've seen people with 
decades of experience who are not competent to design any meaningful SW. 
They're among that large proportion of developers who will never be more 
than coders. Customers are happy with anything that works and they can 
afford; I've seen customer satisfaction with very poorly designed SW.

There may be cases where global variables are the correct design 
approach, but I have yet to see one.

> While it is true that all SW people are not equal, I don't see what 
> that has to do with the issue of global variables, nor do I see what 
> problem recognizing that might be a solution to.

Once you recognize that, you don't allow the coders to design SW. That 
gets rid of most poor design, including designs with large numbers of 
undocumented global variables.

As I said above, I have many designs that are not as good as they could 
be, and some of them are freely available for anyone to look at. My 
primary problem is with designs where the global variable is the 
determining feature, with large numbers of them, and the fact that in 
over 30 yrs I've never seen a case where global variables were the best 
approach. GDS is probably not in that category. I'm not saying the GDS 
SW is poorly designed (I've seen enough of your work to suspect it 
probably isn't), but I suspect that the design could be improved and 
that the improvement would eliminate the global variables. Whether the 
improvement in design quality would be worth the effort to achieve it 
now, I can't say. At the time of initial design, it almost certainly was.

-- 
Jeff Carter
"In the frozen land of Nador they were forced to
eat Robin's minstrels, and there was much rejoicing."
Monty Python & the Holy Grail
70



^ permalink raw reply	[flat|nested] 34+ messages in thread

* Re: [SPARK] Code safety and information hiding
  2006-08-19 12:47               ` Björn Persson
@ 2006-08-20  3:58                 ` Jeffrey R. Carter
  2006-08-20 11:35                   ` Björn Persson
  0 siblings, 1 reply; 34+ messages in thread
From: Jeffrey R. Carter @ 2006-08-20  3:58 UTC (permalink / raw)


Bj�rn Persson wrote:
> 
> Well, maybe, but I think it sounds like the variable isn't local 
> anywhere at all, which would mean it's global.

We're talking about variables that are not global (in a package spec), 
not local(in the innermost declarative region that references them), and 
not state variables (in a package body and referenced by the public 
operations of the package). In the spectrum of locality they're 
intermediate.

In terms of use, we have global, state, and local variables, and these 
things, that don't fit any of those concepts.

-- 
Jeff Carter
"In the frozen land of Nador they were forced to
eat Robin's minstrels, and there was much rejoicing."
Monty Python & the Holy Grail
70



^ permalink raw reply	[flat|nested] 34+ messages in thread

* Re: [SPARK] Code safety and information hiding
  2006-08-20  3:58                 ` Jeffrey R. Carter
@ 2006-08-20 11:35                   ` Björn Persson
  0 siblings, 0 replies; 34+ messages in thread
From: Björn Persson @ 2006-08-20 11:35 UTC (permalink / raw)


Jeffrey R. Carter wrote:
> We're talking about variables that are not global (in a package spec), 
> not local(in the innermost declarative region that references them), and 
> not state variables (in a package body and referenced by the public 
> operations of the package). In the spectrum of locality they're 
> intermediate.
> 
> In terms of use, we have global, state, and local variables, and these 
> things, that don't fit any of those concepts.

Precisely. They're intermediate, but "intermediately local" is even more 
unwieldy. (Is "intermediately" even a word?) How about "half-local"? 
"Semilocal"?

-- 
Bj�rn Persson                              PGP key A88682FD
                    omb jor ers @sv ge.
                    r o.b n.p son eri nu



^ permalink raw reply	[flat|nested] 34+ messages in thread

* Re: [SPARK] Code safety and information hiding
  2006-08-20  3:52         ` Jeffrey R. Carter
@ 2006-08-20 19:06           ` Stephen Leake
  2006-08-21  1:07             ` Jeffrey R. Carter
  2006-08-21 11:30             ` Colin Paul Gloster
  0 siblings, 2 replies; 34+ messages in thread
From: Stephen Leake @ 2006-08-20 19:06 UTC (permalink / raw)


"Jeffrey R. Carter" <spam.not.jrcarter@acm.not.spam.org> writes:

> Stephen Leake wrote:
>> I think I'll choose to take offense at this statement (it's 5:26 AM,
>> and I can't sleep because I've got a bit of the flu, so I claim the
>> right :).
>
> I have a bad cold, and did when I wrote the statement to which you're
> responding, so I claim the right to argue back. Let's spray our addled
> perceptions into c.l.a, where someone will reference them as
> definitive in the future.

Ok, sounds like fun :)

>> I have an application called Goddard Dynamic Simulator (GDS); it is
>> used to test flight software and hardware for NASA Goddard (yes, I am
>>  a rocket scientist). It has 90,000 lines of code, mostly Ada, some C
>>  and VHDL.
>
> I've never been sure what a "rocket scientist" is. Is it someone who
> deals with the theory of anaerobic propulsion systems? Or is it a more
> general science dealing with launch systems overall?

In this case, it's anyone vaguely associated with launching rockets,
or working for NASA. It's intended as an assertion of authority,
hoping to instill fear and obediance in the audience.

> In any case, being a scientist is probably not a qualification for
> designing actual systems. Scientists deal with theory; engineers with
> creating systems. Physicists are not necessarily competent to design
> bridges; civil engineers are.

Good point. But "rocket scientists" are actually typically engineers.
The original term was for the people who made the first large rockets
actually fly; they were certainly engineers.

>> However, there are some global variables. I thought long and hard
>> about each one, and decided they are the best solution to the
>> problem.
>
> Some is probably better than lots. 

Agreed.

> With "some" they might be well documented. 

They are.

> As I've said, I've seen large, safety-critical systems designed
> around thousands of undocumented global variables. 

Ok, that's definitely bad.

I haven't seen a system with that particular flaw, but I have seen
plenty of bad systems.

> I think it would be faster and easier to redesign and reimplement
> these systems than to understand them well enough to safely make
> changes to a small part of them.

Yes.

>> This design has evolved thru several iterations of similar systems.
>> They all have a global symbol table.
>
> So, as a modifier of the system, without reading and understanding all
> parts of the system that may access this variable, it's OK for me to
> write to this variable whenever it's convenient?

Of course not. Now you are setting up a strawman.

In my system, as you alluded to above, the use of each global variable
is well documented; programmers are expected to follow the rules in
the documentation. 

Of course, every time I add a new programmer to the team, they
discover new ways to (mis-)use the globals that were not covered by
the documentation :).

>> type Distribute_Mode_Type is (Master_Mode, Remote_Mode, Single_Mode);
>> Distribute_Mode : Distribute_Mode_Type := Single_Mode;
>
> Again, it must be reasonable and meaningful for me to change the SW to
> write this variable whenever it suits me.
>
> If that's not the case, then I claim this should not be a variable.
> Instead of being able to write
>
> X.Distribute_Mode := X.Master_Mode;
>
> I should have to call something like
>
> function Request_Distribute_Mode_Change
>     (New_Mode : Distribute_Mode_Type)
> return Boolean;
> -- Request mode change to New_Mode.
> -- Returns True if the mode change is legal; False otherwise.
>
> All the details of when a mode change may occur should be encapsulated
> with the current mode value.

Ah. You want the code to enforce the design rules. That's not possible
in general. Ada allows enforcing some design rules, but not ones at
this level.

In fact, for this particular variable, the rule is "only the
environment task may write to this variable, and only before any other
tasks are started".

People modifying the code must understand the design.

I have been tempted to write some ASIS programs to enforce more of the
design rules. One that people keep breaking is "modules must not write
to their own Input symbols". But this would be a complex program
(worse than Auto_Text_IO, for example), so I haven't done it yet.

Hmm. Now that I think about it, it would be easy to implement a
run-time check for that rule. But it would be a waste of time in the
production system. Might still be worth it; I have other run-time
checks for similar rules (in particular, "symbols must be written
before being read") that are hard to check otherwise.

> On the 3rd hand, systems generally are either distributed or not, and
> that doesn't change during execution. In that case, this is
> essentially a constant. If the actual mode is determined at run time
> during start up, then probably the value should be encapsulated with
> the logic that determines it, and the resulting value be made
> available to the rest of the system through a function.

That would be essentially a globally visible getter/setter; the getter
must be globally visible, but the environment task which calls the
setter should not be. I don't see any way to enforce the rule of which
task is allowed to set the variable at run time.

In practice, the rule of how this variable is set has never been broken.

> In this latter case, there may also be a race condition. What if one
> part of the system reads this and gets the default value before its
> actual value is determined? It's probably better to control that
> locally than otherwise.

In general, that's a reasonable goal. In this particular case, it's
not possible.

>>    Ignore_Hardware_Errors : Boolean := False;
>>    --  Set True for unit tests when hardware is not present or should
>>    --  be ignored.
>
> Shouldn't that be "Boolean_Type"?

It would be if I was writing the Ada language. We're stuck with
"Boolean". 

> This is documented, and shows that it isn't a variable. Clearly this
> should have the same value for an entire execution; I've never seen SW
> that switches between unit test and other modes during execution. I
> suspect your SW would be clearer if this were a constant.

During any particular run of the full production system, this is a
constant; usually False but occasionally True (if some important
hardware is absent). Thus it is set by the environment task at
startup, just like Distribute_Mode.

During runs of many unit tests together (under an AUnit test harness),
this value changes between False and True. Some unit tests use
hardware emulation code, and can check for hardware errors. Other unit
tests have no emulation code, and must ignore them.

>> I claim to be competent to design SW; I have 20 years of experience,
>> and at least 10 monetary awards for outstanding performance, together
>>  with high praise from my (internal) customers, to prove that. My
>> system has a few global variables because they are the right solution
>>  to the problem.
>
> Perhaps. Who modifies the system? 

That is the important question. For now, it is a team led by me.

> Add 1 undocumented global variable to a system, and you generally
> increase the coupling and decrease the cohesion. 

That is not just true of variables; add 1 undocumented
function/procedure/package/task to the system, and you have a problem.

The key notion here is "documentation"; any system must be documented,
so that maintainers understand it before modifying it.

> You understand the system, but after you're hit by a truck, how easy
> is it for someone who doesn't have any experience with the system to
> figure out how it works?

That is the important criterium for how good the documentation is. 

When one of my team members or customers asks a question about how to
use the system, I try to look in the documentation to answer it first.
If the answer isn't there, I fix the documentation as the answer to
the question.

Of course, when there's a crunch on, questions get answered more
directly. So the documentation isn't perfect. But it is intended to be
adequate. 

>> You have not said why getter/setter would be better for these
>> variables. I agree with Robert; they are just more verbose.
>
> I don't think they're better. I said that if global variables were not
> available, those who would try to base their designs around them might
> not think of using such operations to mimic them.

Hmm. I guess I don't know what you mean by this. Above, you suggested
replacing Distribute mode by a getter/setter, where the setter
enforced the design rules. I assumed you meant that getter/setter
design was better than the global variable it replaces. Now you are
saying something else, but I don't know what.

>> Hmm. You could try to impose control over what parts of the system
>> are "allowed" to write the variables, as opposed to reading them. But
>> that would require an elaborate system of IDs for various parts of
>> the system (which does not otherwise exist); definitely not worth it.
>
> You might simply document who may write and who may read such
> variables. 

That is what I'm doing.

> That would be a big improvement in the global-centric systems I've
> seen. Of course, that goes against the basic Ada philosophy that
> packages should not be concerned with who their clients are. 

While that philosophy is useful for packages that encapsulate a
logical function, it is clearly not true for packages that declare
global variables; they exist precisely for the use of the system as a
whole, not of the package that happens to declare them.

As with most other good ideas in design philosophy, there are times
where this one doesn't work.

> That's something that's not always achievable in large, real SW
> systems. 

Exactly.

> In general, values should be encapsulated with the logic that
> generates or modifies them, 

Yes. And "the logic" can be as small as a 10 line function, or as
large as a 90k multi-cpu program; each has need of some state that is
visible to the entire subsystem.

> Now, I've worked on systems with physical redundancy, so that one
> processor is the currently active one, and the others shadow it and
> are prepared to take over if it fails. I've worked on such systems
> where the determination of which is the active processor is made by
> another part of the system, so it is necessary to distribute that
> value to the processors. In that case, the SW pretends that it
> determines the value; for example, there's a module that encapsulates
> the value and provides access to it to other parts of the SW. There
> isn't a procedure Set for the value; rather, the module has an
> operation that receives and processes the message that changes the
> value.

How did you set the variable in unit tests?

>> I'll make a counter claim; people who claim global variables are
>> _always_ bad should not be designing large complex systems; the
>> systems will be more complex than necessary, which is definitely a
>> Bad Thing.
>
> I have over 30 yrs of professional SW development experience, and I
> still find myself doing things I know I shouldn't. 

That's true for me as well.

> Hopefully I catch them most of the time in the important cases. But
> I've seen people with decades of experience who are not competent to
> design any meaningful SW. 

Also true.

> They're among that large proportion of developers who will never be
> more than coders. Customers are happy with anything that works and
> they can afford; I've seen customer satisfaction with very poorly
> designed SW.

That I have not seen. Well, I guess I have to count Microsoft software
in that; some people seem happy with it.

But all poorly designed systems that I know of, in my area of
expertise, have unhappy customers.

> There may be cases where global variables are the correct design
> approach, but I have yet to see one.

now you have :).

>> While it is true that all SW people are not equal, I don't see what
>> that has to do with the issue of global variables, nor do I see what
>> problem recognizing that might be a solution to.
>
> Once you recognize that, you don't allow the coders to design SW. That
> gets rid of most poor design, including designs with large numbers of
> undocumented global variables.

"large numbers" and "undocumented" are the key here, and as I pointed
out above, that description applies to other aspects of the software
as well; large numbers of small functions, or large numbers of
threads, are just as bad (possibly worse) as large numbers of global
variables.

> I'm not saying the GDS SW is poorly designed (I've seen enough of
> your work to suspect it probably isn't),

Ok, good. However, I think you will agree that your initial statement
implied that it was, since it does have some global variables. Which
is why I responded.

> but I suspect that the design could be improved and that the
> improvement would eliminate the global variables. 

The design could certainly be improved. But eliminating these global
variables isn't even on my list.

> Whether the improvement in design quality would be worth the effort
> to achieve it now, I can't say. At the time of initial design, it
> almost certainly was.

Well, that is a judgement call. At the time of the initial design, I
decided that eliminating the global variables was more costly than the
risk of them being misused. 

It does depend on the quality of the maintenance team; whether they
truly understand the system before modifying it. But someone who
doesn't understand a system will still be tempted to "just add a
global variable to fix this". Which is why adding complexity just for
the sake of reducing global variables is not worth it; it makes the
system that much harder to understand.

-- 
-- Stephe



^ permalink raw reply	[flat|nested] 34+ messages in thread

* Re: [SPARK] Code safety and information hiding
  2006-08-20 19:06           ` Stephen Leake
@ 2006-08-21  1:07             ` Jeffrey R. Carter
  2006-08-21  7:25               ` Maciej Sobczak
  2006-08-21 11:30             ` Colin Paul Gloster
  1 sibling, 1 reply; 34+ messages in thread
From: Jeffrey R. Carter @ 2006-08-21  1:07 UTC (permalink / raw)


Stephen Leake wrote:
> 
> In this case, it's anyone vaguely associated with launching rockets,
> or working for NASA. It's intended as an assertion of authority,
> hoping to instill fear and obediance in the audience.

I guess I'm a rocket scientist, too, then. I've been involved with SW 
for space systems.

> Good point. But "rocket scientists" are actually typically engineers.
> The original term was for the people who made the first large rockets
> actually fly; they were certainly engineers.

Precision in language for technical subjects is a Good Thing.

> In my system, as you alluded to above, the use of each global variable
> is well documented; programmers are expected to follow the rules in
> the documentation. 

It sounds as if we're in general agreement.

> Of course, every time I add a new programmer to the team, they
> discover new ways to (mis-)use the globals that were not covered by
> the documentation :).

Of course. If the global variables weren't there, they'd be stymied.

> That would be essentially a globally visible getter/setter; the getter
> must be globally visible, but the environment task which calls the
> setter should not be. I don't see any way to enforce the rule of which
> task is allowed to set the variable at run time.

There would be no setter. You'd have something like

package Mode_Handler is
    type Mode_ID is (...);

    function Current_Mode return Mode;
end Mode_Handler;

The body of Mode_Handler is responsible for maintaining the current 
mode; if necessary, callers to Current_Mode block until it has a value. 
This can be achieved by the environment task executing the 
initialization code for the package during elaboration, or by an 
initialization task in the package body.

> It would be if I was writing the Ada language. We're stuck with
> "Boolean". 

I'm glad you're not. "_Type" on the end of names is just 5 wasted 
characters. File_Type is about the only poorly named predefined type in 
the language. But let's not get into that discussion again. I've worked 
on systems that used the _Type convention, and it's workable.

> That is not just true of variables; add 1 undocumented
> function/procedure/package/task to the system, and you have a problem.

Yes, but not generally an increase in coupling and decrease in cohesion.

> Hmm. I guess I don't know what you mean by this. Above, you suggested
> replacing Distribute mode by a getter/setter, where the setter
> enforced the design rules. I assumed you meant that getter/setter
> design was better than the global variable it replaces. Now you are
> saying something else, but I don't know what.

I trust I've clarified this.

> Yes. And "the logic" can be as small as a 10 line function, or as
> large as a 90k multi-cpu program; each has need of some state that is
> visible to the entire subsystem.

They need to be able to access the value, but not to modify it. Global 
variables may be modified from anywhere.

> How did you set the variable in unit tests?

By faking the message.

> That I have not seen. Well, I guess I have to count Microsoft software
> in that; some people seem happy with it.

The customers of the SW designed around large numbers of undocumented 
global variables seemed satisfied with it. They weren't looking at or 
modifying the SW. In each case there were 1 or 2 people who had the 
whole system in their heads; that's the reason they were able to modify 
it. I guess I have a smaller head than they. And if those people ceased 
to be available, there would be big trouble.

> now you have :).

I still don't agree.

> "large numbers" and "undocumented" are the key here, and as I pointed
> out above, that description applies to other aspects of the software
> as well; large numbers of small functions, or large numbers of
> threads, are just as bad (possibly worse) as large numbers of global
> variables.

I'd be perfectly happy with an Ada-like language that didn't allow 
variables in package specs.

For the Mine Detector game, I have 2 protected Booleans in the spec of 
the package that models the mine field. (They're protected because the 
original design had a task so that user input could be obtained while 
the model of the mine field did its thing.) That's not a terrible 
design, but with the changes needed to use GtkAda (which involved 
getting rid of the task), in retrospect it would be better to store the 
values in the user-interface package, which determines their values, and 
have the mine-field package ask the user-interface package for them.

As you're probably aware, rules with "always" in them always have 
exceptions (including this rule). I have a rule that says always avoid 
global variables. I'll accept a small number of well documented global 
variables sometimes if the alternative is worse.

-- 
Jeff Carter
"Many times we're given rhymes that are quite unsingable."
Monty Python and the Holy Grail
57



^ permalink raw reply	[flat|nested] 34+ messages in thread

* Re: [SPARK] Code safety and information hiding
  2006-08-21  1:07             ` Jeffrey R. Carter
@ 2006-08-21  7:25               ` Maciej Sobczak
  2006-08-21 19:31                 ` Jeffrey R. Carter
  0 siblings, 1 reply; 34+ messages in thread
From: Maciej Sobczak @ 2006-08-21  7:25 UTC (permalink / raw)


Jeffrey R. Carter wrote:

> As you're probably aware, rules with "always" in them always have 
> exceptions (including this rule). I have a rule that says always avoid 
> global variables. I'll accept a small number of well documented global 
> variables sometimes if the alternative is worse.

It's interesting to see this discussion, especially after the posts 
revealing that it's not really clear what "global" means.

Let's say I have a program composed of some subroutines or packages. 
Each subroutine has some local variables and each package has some state 
  and together they all cooperate according to what the whole is 
supposed to do.
Then I decide to break the system into separate processes, and for the 
sake of discussion what was a subroutine (or a package) originally 
becomes a separate process, all communicating using some form of IPC and 
still cooperating to achieve the supposed goals.

The point is that while chopping the system into pieces, what was local 
(or state) variable originally became global in the resulting smaller 
program.

Now - did I break SW principles and should I go to hell for making N 
programs with M global variables in each?
After all, if I draw the whole on the whiteboard, the diagram is the 
same as it was at the beginning, with boxes encapsulating state and 
arrows depicting the only possible interactions. So? :-)


-- 
Maciej Sobczak : http://www.msobczak.com/
Programming    : http://www.msobczak.com/prog/



^ permalink raw reply	[flat|nested] 34+ messages in thread

* Re: [SPARK] Code safety and information hiding
  2006-08-20 19:06           ` Stephen Leake
  2006-08-21  1:07             ` Jeffrey R. Carter
@ 2006-08-21 11:30             ` Colin Paul Gloster
  2006-08-22 10:51               ` Stephen Leake
  1 sibling, 1 reply; 34+ messages in thread
From: Colin Paul Gloster @ 2006-08-21 11:30 UTC (permalink / raw)


Stephen A. Leake had written:

"[..]
type Distribute_Mode_Type is (Master_Mode, Remote_Mode, Single_Mode);
Distribute_Mode : Distribute_Mode_Type := Single_Mode;
[..]"

Jeffrey R. Carter responded:

"[..]
Again, it must be reasonable and meaningful for me to change the SW to
write this variable whenever it suits me.

If that's not the case, then I claim this should not be a variable.
Instead of being able to write

X.Distribute_Mode := X.Master_Mode;

I should have to call something like

function Request_Distribute_Mode_Change
    (New_Mode : Distribute_Mode_Type)
return Boolean;
-- Request mode change to New_Mode.
-- Returns True if the mode change is legal; False otherwise.

All the details of when a mode change may occur should be encapsulated
with the current mode value.
[..]"



During the next clock cycle it might no longer be legal to change mode.



On Sun, 20 Aug 2006, Stephen Leake wrote:

"[..]

Ah. You want the code to enforce the design rules. That's not possible
in general. Ada allows enforcing some design rules, but not ones at
this level.

In fact, for this particular variable, the rule is "only the
environment task may write to this variable, and only before any other
tasks are started".

People modifying the code must understand the design."


Obviously, if only one task exists which is permitted to write to the 
variable, then a getter and a setter are sufficient, unless someone 
modifies the code so that another task can also write. I accept that you 
have been posting about trying to make it impossible for people to make 
such a modification, and that this is not strictly achievable, but the 
getter and setter methods paradigm is well understood widely when only one 
owner is allowed to call the setter method, so why would you be especially 
worried that someone would not realize this for this simpler example you 
presented?


Stephen Leake has written:

"[..]

Hmm. Now that I think about it, it would be easy to implement a
run-time check for that rule. But it would be a waste of time in the
production system. Might still be worth it; I have other run-time
checks for similar rules (in particular, "symbols must be written
before being read") that are hard to check otherwise.

[..]"

Was simply Ada code run in the application to check the rule meant by 
that, or do you have customized run-time checks in your GNAT run-time 
kernel?

Regards,
Colin Paul Gloster



^ permalink raw reply	[flat|nested] 34+ messages in thread

* Re: [SPARK] Code safety and information hiding
  2006-08-21  7:25               ` Maciej Sobczak
@ 2006-08-21 19:31                 ` Jeffrey R. Carter
  2006-08-21 19:58                   ` Dmitry A. Kazakov
  0 siblings, 1 reply; 34+ messages in thread
From: Jeffrey R. Carter @ 2006-08-21 19:31 UTC (permalink / raw)


Maciej Sobczak wrote:
> 
> It's interesting to see this discussion, especially after the posts 
> revealing that it's not really clear what "global" means.

We were discussing "true" global variables: variables in package 
specifications.

> Let's say I have a program composed of some subroutines or packages. 
> Each subroutine has some local variables and each package has some state 
>  and together they all cooperate according to what the whole is supposed 
> to do.
> Then I decide to break the system into separate processes, and for the 
> sake of discussion what was a subroutine (or a package) originally 
> becomes a separate process, all communicating using some form of IPC and 
> still cooperating to achieve the supposed goals.

Now each main subprogram that was a subprogram (Ada doesn't have 
subroutines) in the original has its own local variables.

Each main subprogram that was a package with state now has its own local 
variables that contain that state.

> The point is that while chopping the system into pieces, what was local 
> (or state) variable originally became global in the resulting smaller 
> program.

I don't see that this is necessary.

-- 
Jeff Carter
"What I wouldn't give for a large sock with horse manure in it."
Annie Hall
42



^ permalink raw reply	[flat|nested] 34+ messages in thread

* Re: [SPARK] Code safety and information hiding
  2006-08-21 19:31                 ` Jeffrey R. Carter
@ 2006-08-21 19:58                   ` Dmitry A. Kazakov
  2006-08-21 21:06                     ` Björn Persson
  0 siblings, 1 reply; 34+ messages in thread
From: Dmitry A. Kazakov @ 2006-08-21 19:58 UTC (permalink / raw)


On Mon, 21 Aug 2006 19:31:10 GMT, Jeffrey R. Carter wrote:

> Maciej Sobczak wrote:
>> 
>> It's interesting to see this discussion, especially after the posts 
>> revealing that it's not really clear what "global" means.
> 
> We were discussing "true" global variables: variables in package 
> specifications.

Packages have scope. Is a variable in the specification of a nested package
"truly" global? Clearly, both "global" and "local" are relative to the
given scope. The third possible status is "orthogonal" (exists in a sibling
scope).

>> Let's say I have a program composed of some subroutines or packages. 
>> Each subroutine has some local variables and each package has some state 
>>  and together they all cooperate according to what the whole is supposed 
>> to do.
>> Then I decide to break the system into separate processes, and for the 
>> sake of discussion what was a subroutine (or a package) originally 
>> becomes a separate process, all communicating using some form of IPC and 
>> still cooperating to achieve the supposed goals.
> 
> Now each main subprogram that was a subprogram (Ada doesn't have 
> subroutines) in the original has its own local variables.

Which are global relatively to the process, and local relatively to the
distributed system as a whole.

> Each main subprogram that was a package with state now has its own local 
> variables that contain that state.
> 
>> The point is that while chopping the system into pieces, what was local 
>> (or state) variable originally became global in the resulting smaller 
>> program.

Which is true without any chopping. Descending a hierarchy of scopes makes
some things global without changing anything.

-- 
Regards,
Dmitry A. Kazakov
http://www.dmitry-kazakov.de



^ permalink raw reply	[flat|nested] 34+ messages in thread

* Re: [SPARK] Code safety and information hiding
  2006-08-21 19:58                   ` Dmitry A. Kazakov
@ 2006-08-21 21:06                     ` Björn Persson
  2006-08-22  7:16                       ` Maciej Sobczak
  2006-08-22  7:27                       ` Dmitry A. Kazakov
  0 siblings, 2 replies; 34+ messages in thread
From: Björn Persson @ 2006-08-21 21:06 UTC (permalink / raw)


Dmitry A. Kazakov wrote:
> On Mon, 21 Aug 2006 19:31:10 GMT, Jeffrey R. Carter wrote:
>> Now each main subprogram that was a subprogram (Ada doesn't have 
>> subroutines) in the original has its own local variables.
> 
> Which are global relatively to the process, and local relatively to the
> distributed system as a whole.

No. They're declared inside the main subprogram and not visible to any 
library-level packages, so they aren't truly global.

-- 
Bj�rn Persson                              PGP key A88682FD
                    omb jor ers @sv ge.
                    r o.b n.p son eri nu



^ permalink raw reply	[flat|nested] 34+ messages in thread

* Re: [SPARK] Code safety and information hiding
  2006-08-21 21:06                     ` Björn Persson
@ 2006-08-22  7:16                       ` Maciej Sobczak
  2006-08-22  9:45                         ` Björn Persson
  2006-08-22  7:27                       ` Dmitry A. Kazakov
  1 sibling, 1 reply; 34+ messages in thread
From: Maciej Sobczak @ 2006-08-22  7:16 UTC (permalink / raw)


Bj�rn Persson wrote:

>>> Now each main subprogram that was a subprogram (Ada doesn't have 
>>> subroutines) in the original has its own local variables.
>>
>> Which are global relatively to the process, and local relatively to the
>> distributed system as a whole.
> 
> No. They're declared inside the main subprogram and not visible to any 
> library-level packages, so they aren't truly global.

This is just hiding from discussion. :-)

If you rigorously stick to some chosen definition, then you can argue 
that such variables are not global.
But I will argue that a variable which is visible everywhere in the 
program (in the sense that every executable piece of code can access 
this variable) is effectively global in that program - it's the 
visibility in any given scope the makes something global or local, all 
the rest is only syntax.
Criticising the use of global variables without considering the full 
context of the given system is somewhat orthodox, even more so if only 
syntax is considered to be a distinguishing factor. I can imagine a 
program that uses global variables where "encapsulating" them into 
separate package(s) would only add clutter, without any real benefit.


-- 
Maciej Sobczak : http://www.msobczak.com/
Programming    : http://www.msobczak.com/prog/



^ permalink raw reply	[flat|nested] 34+ messages in thread

* Re: [SPARK] Code safety and information hiding
  2006-08-21 21:06                     ` Björn Persson
  2006-08-22  7:16                       ` Maciej Sobczak
@ 2006-08-22  7:27                       ` Dmitry A. Kazakov
  1 sibling, 0 replies; 34+ messages in thread
From: Dmitry A. Kazakov @ 2006-08-22  7:27 UTC (permalink / raw)


On Mon, 21 Aug 2006 21:06:15 GMT, Bj�rn Persson wrote:

> Dmitry A. Kazakov wrote:
>> On Mon, 21 Aug 2006 19:31:10 GMT, Jeffrey R. Carter wrote:
>>> Now each main subprogram that was a subprogram (Ada doesn't have 
>>> subroutines) in the original has its own local variables.
>> 
>> Which are global relatively to the process, and local relatively to the
>> distributed system as a whole.
> 
> No. They're declared inside the main subprogram and not visible to any 
> library-level packages, so they aren't truly global.

So "truly global" = library level?

What about a program P1 invoking compiler on P2, linking and executing the
result? Are library things of P2 truly global?

-- 
Regards,
Dmitry A. Kazakov
http://www.dmitry-kazakov.de



^ permalink raw reply	[flat|nested] 34+ messages in thread

* Re: [SPARK] Code safety and information hiding
  2006-08-22  7:16                       ` Maciej Sobczak
@ 2006-08-22  9:45                         ` Björn Persson
  2006-08-22 12:42                           ` Maciej Sobczak
  0 siblings, 1 reply; 34+ messages in thread
From: Björn Persson @ 2006-08-22  9:45 UTC (permalink / raw)


Maciej Sobczak wrote:
> But I will argue that a variable which is visible everywhere in the 
> program (in the sense that every executable piece of code can access 
> this variable) is effectively global in that program

Exactly. And if you have:

package Pack is
    procedure Piece_Of_Code;
end Pack;

with Pack;
procedure Main_Subprogram is
    Variable : Natural;
begin
    Pack.Piece_Of_Code;
end Main_Subprogram;

then Piece_Of_Code can't access Variable, so Variable isn't effectively 
global, right?

-- 
Bj�rn Persson                              PGP key A88682FD
                    omb jor ers @sv ge.
                    r o.b n.p son eri nu



^ permalink raw reply	[flat|nested] 34+ messages in thread

* Re: [SPARK] Code safety and information hiding
  2006-08-21 11:30             ` Colin Paul Gloster
@ 2006-08-22 10:51               ` Stephen Leake
  0 siblings, 0 replies; 34+ messages in thread
From: Stephen Leake @ 2006-08-22 10:51 UTC (permalink / raw)


Colin Paul Gloster <Colin_Paul_Gloster@ACM.org> writes:

> Stephen Leake has written:
>
> "[..]
>
> Hmm. Now that I think about it, it would be easy to implement a
> run-time check for that rule. But it would be a waste of time in the
> production system. Might still be worth it; I have other run-time
> checks for similar rules (in particular, "symbols must be written
> before being read") that are hard to check otherwise.
>
> [..]"
>
> Was simply Ada code run in the application to check the rule meant by 
> that, or do you have customized run-time checks in your GNAT run-time 
> kernel?

Just Ada code; no modifications to the compiler run-time.

-- 
-- Stephe



^ permalink raw reply	[flat|nested] 34+ messages in thread

* Re: [SPARK] Code safety and information hiding
  2006-08-22  9:45                         ` Björn Persson
@ 2006-08-22 12:42                           ` Maciej Sobczak
  0 siblings, 0 replies; 34+ messages in thread
From: Maciej Sobczak @ 2006-08-22 12:42 UTC (permalink / raw)


Bj�rn Persson wrote:

>> But I will argue that a variable which is visible everywhere in the 
>> program (in the sense that every executable piece of code can access 
>> this variable) is effectively global in that program
> 
> Exactly. And if you have:
> 
> package Pack is
>    procedure Piece_Of_Code;
> end Pack;
> 
> with Pack;
> procedure Main_Subprogram is
>    Variable : Natural;
> begin
>    Pack.Piece_Of_Code;
> end Main_Subprogram;
> 
> then Piece_Of_Code can't access Variable, so Variable isn't effectively 
> global, right?

In this case right, although going down this path one could argue that 
there are no global variables at all, because for every such variable 
there exists at least one package (like Ada.Charaters), that cannot 
access it. :-)


-- 
Maciej Sobczak : http://www.msobczak.com/
Programming    : http://www.msobczak.com/prog/



^ permalink raw reply	[flat|nested] 34+ messages in thread

* Re: [SPARK] Code safety and information hiding
  2006-08-18 23:02   ` Robert A Duff
  2006-08-19  5:40     ` Jeffrey R. Carter
@ 2006-08-23  9:44     ` Peter Amey
  2006-08-23 22:37       ` Jeffrey R. Carter
  1 sibling, 1 reply; 34+ messages in thread
From: Peter Amey @ 2006-08-23  9:44 UTC (permalink / raw)




Robert A Duff wrote:
> "Jeffrey R. Carter" <spam.not.jrcarter@acm.not.spam.org> writes:
> 
> 
>>[Aside: I really don't like the use of the term "global" for state
>>variables. True global variables (in package specs) should be illegal;
>>state variables are a different cup of fish and should not be tainted by
>>the "global" label.]
> 
> 
> I think the terms "global" and "local" are most useful if they are
> relative to something.  A variable can be more global or less global.
> The Ada RM agrees with that (not surprising, since I wrote
> that part ;-)).  See quote below.

That's certainly the design decision we made with SPARK.  The term 
global is always relative to the place  where you are asking the 
question.  If an entity is declared outside the declarative part of the 
place from which you are looking it is global otherwise it is local.  A 
local variable of a subprogram may well be a global to a nested 
subprogram for example.  SPARK's global annotation eliminates "hole in 
scope" issues (as well as doing other useful things).

[snip]
> 
> I don't agree that package-spec variables should be illegal.  Such a
> rule accomplishes nothing, since the programmer can just have a getter
> and a setter, which is just as evil.  In some rare cases, a package-spec
> variable makes sense, and in those cases, the getter/setter method is no
> better (just more verbose).

SPARK doesn't prohibit package-spec variables (actually it did in the 
very early days but a large and influential customer made us change our 
minds); however, it does nag you in various ways if you make use of 
them.  Abstract own variables and refinement clauses are a much better 
solution!

> 
> So I like the SPARK syntax for "global".  It means so-and-so variable is
> global to this procedure, not necessarily global to the whole program,
> or global to that part of the program that with's certain package, or
> global to the whole world.
> 

Thanks!


Peter




^ permalink raw reply	[flat|nested] 34+ messages in thread

* Re: [SPARK] Code safety and information hiding
  2006-08-23  9:44     ` Peter Amey
@ 2006-08-23 22:37       ` Jeffrey R. Carter
  2006-08-24 10:55         ` Peter Amey
  0 siblings, 1 reply; 34+ messages in thread
From: Jeffrey R. Carter @ 2006-08-23 22:37 UTC (permalink / raw)


Peter Amey wrote:
> 
> That's certainly the design decision we made with SPARK.  The term 
> global is always relative to the place  where you are asking the 
> question.  If an entity is declared outside the declarative part of the 
> place from which you are looking it is global otherwise it is local.  A 
> local variable of a subprogram may well be a global to a nested 
> subprogram for example.  SPARK's global annotation eliminates "hole in 
> scope" issues (as well as doing other useful things).

To my mind, in a well designed system, all the "global" variables will 
be state variables, and I'd prefer to reserve the term "global" for 
package-spec variables.

> SPARK doesn't prohibit package-spec variables (actually it did in the 
> very early days but a large and influential customer made us change our 
> minds); however, it does nag you in various ways if you make use of 
> them.  Abstract own variables and refinement clauses are a much better 
> solution!

I think it would be better if you'd educated your customer on how to use 
that better solution, and kept SPARK as it was.

Interesting that my aside on my personal preference for terminology has 
generated so much traffic.

-- 
Jeff Carter
"Brave Sir Robin ran away."
Monty Python and the Holy Grail
59



^ permalink raw reply	[flat|nested] 34+ messages in thread

* Re: [SPARK] Code safety and information hiding
  2006-08-23 22:37       ` Jeffrey R. Carter
@ 2006-08-24 10:55         ` Peter Amey
  2006-08-24 23:33           ` Jeffrey R. Carter
  0 siblings, 1 reply; 34+ messages in thread
From: Peter Amey @ 2006-08-24 10:55 UTC (permalink / raw)




Jeffrey R. Carter wrote:
> Peter Amey wrote:
> 
[snip]
> 
>> SPARK doesn't prohibit package-spec variables (actually it did in the 
>> very early days but a large and influential customer made us change 
>> our minds); however, it does nag you in various ways if you make use 
>> of them.  Abstract own variables and refinement clauses are a much 
>> better solution!
> 
> 
> I think it would be better if you'd educated your customer on how to use 
> that better solution, and kept SPARK as it was.

Now we probably would, then (1991?) we were very small and we _really_ 
needed that customer!

Our nagging really is persistent though and I don't think any current 
SPARK projects continue to abuse own variable visibility.

> 
> Interesting that my aside on my personal preference for terminology has 
> generated so much traffic.
> 

Indeed, unexpected rambles are one of the few remaining pleasures of usenet!

Peter




^ permalink raw reply	[flat|nested] 34+ messages in thread

* Re: [SPARK] Code safety and information hiding
  2006-08-24 10:55         ` Peter Amey
@ 2006-08-24 23:33           ` Jeffrey R. Carter
  0 siblings, 0 replies; 34+ messages in thread
From: Jeffrey R. Carter @ 2006-08-24 23:33 UTC (permalink / raw)


Peter Amey wrote:
> 
> Our nagging really is persistent though and I don't think any current 
> SPARK projects continue to abuse own variable visibility.

I guess I ought to try it someday to see.

-- 
Jeff Carter
"Now go away or I shall taunt you a second time."
Monty Python & the Holy Grail
07



^ permalink raw reply	[flat|nested] 34+ messages in thread

end of thread, other threads:[~2006-08-24 23:33 UTC | newest]

Thread overview: 34+ messages (download: mbox.gz / follow: Atom feed)
-- links below jump to the message on this page --
2006-08-16  7:56 [SPARK] Code safety and information hiding Maciej Sobczak
2006-08-16  8:53 ` roderick.chapman
2006-08-16 11:18   ` Stuart
2006-08-16 13:23     ` Maciej Sobczak
2006-08-16 19:49 ` [SPARK] " Jeffrey R. Carter
2006-08-17  7:01   ` Maciej Sobczak
2006-08-17 18:08     ` Jeffrey R. Carter
2006-08-17 20:00       ` Björn Persson
2006-08-18  1:22         ` Jeffrey R. Carter
2006-08-18 19:39           ` Björn Persson
2006-08-19  5:35             ` Jeffrey R. Carter
2006-08-19 12:47               ` Björn Persson
2006-08-20  3:58                 ` Jeffrey R. Carter
2006-08-20 11:35                   ` Björn Persson
2006-08-18 23:02   ` Robert A Duff
2006-08-19  5:40     ` Jeffrey R. Carter
2006-08-19  9:49       ` Stephen Leake
2006-08-20  3:52         ` Jeffrey R. Carter
2006-08-20 19:06           ` Stephen Leake
2006-08-21  1:07             ` Jeffrey R. Carter
2006-08-21  7:25               ` Maciej Sobczak
2006-08-21 19:31                 ` Jeffrey R. Carter
2006-08-21 19:58                   ` Dmitry A. Kazakov
2006-08-21 21:06                     ` Björn Persson
2006-08-22  7:16                       ` Maciej Sobczak
2006-08-22  9:45                         ` Björn Persson
2006-08-22 12:42                           ` Maciej Sobczak
2006-08-22  7:27                       ` Dmitry A. Kazakov
2006-08-21 11:30             ` Colin Paul Gloster
2006-08-22 10:51               ` Stephen Leake
2006-08-23  9:44     ` Peter Amey
2006-08-23 22:37       ` Jeffrey R. Carter
2006-08-24 10:55         ` Peter Amey
2006-08-24 23:33           ` Jeffrey R. Carter

This is a public inbox, see mirroring instructions
for how to clone and mirror all data and code used for this inbox