>Global variables means non-object-oriented, non-reusable,
>non-understandable, non-maintainable code. Try building a large project
>with everything global and find out!

Your friend and mine, the Delphi IDE automatically creates a global variable
for each form you design.  If they're that bad, why would the IDE create
them?  From a simplicity point of view, they can come in very handy.  In the
case of global form variables, I usually put something like this in my
Form's OnDestroy event:

procedure TMyForm.FormDestroy( Sender : TObject );
  begin
  if  self = MyForm then
    MyForm := nil;
  end;

At least that way the global is kept up to date, so code can use if
assigned( MyForm ) etc.

Another way of dealing with the global form variable declaration is to
remove the form variable and create some kind of constructor variable. eg:

type
  TMyForm = class( TForm )
    // stuff that your TMyForm should be able to do
    end;

then instead of
var
  MyForm : TMyForm;

delete the IDE created variable and add

type
  TCreateMyForm = function( aOwner : TComponent ) : TMyForm;

var
  CreateMyForm : TMyForm;

In the implementation section of your unit, create an actual virtual
constructor like

function DefaultCreateMyForm( aOwner : TComponent ) : TMyForm;
  begin
  result := TMyForm.Create( aOwner );
  end;


in the initialization section of the same unit you can put

initialization
  @CreateMyForm := @DefaultCreateMyForm;
end.

The @ signs are needed.

The upshot of all of this is that you can now have code that does something
like

  if assigned( CreateMyForm ) then
    with CreateMyForm( self ) do
       try
          ShowModal;
      finally
          free;
          end;


Woopee!  But the good bit, is that now you have a global virtual form
constructor to work with in your code, it can be overriden without needing
to change anything in the original code that called it.


eg:

interface
  uses MyForm;

  TMyReallyNeatForm = class( TMyForm )
   // something that makes your really neat form really neat
  end;

Build a virtual constructor in the same unit (implementation section):

  function CreateMyReallyNeatFormForm( aOwner : TComponent ) : TMyForm;
     begin
      result := TMyReallyNeatFormCreate( aOwner );
    end;

and in the initialization section of the RealllyNeatForm unit

initialization
  @CreateMyForm := @CreateMyReallyNeatForm;
end.


You can do things like chaining (and you probably should if you are loading
and unloading packages)  but the point is that without those global
variables, you couldn't do this at all.

If you can get your head around how this stuff can be made to work for you,
then you probably have the basis for a good argument for using global
variables.  If not, then spend some more time thinking about why a variable
should be global or not.

Some globals that I use regularly are Application and Screen.  Can you
imagine trying to do much in Delphi if they weren't global?  If you think
about why they are made global, and why form variables are made global, the
whole global versus local argument starts to make sense.

It should be global if  It NEEDS to be referred to from anywhere.  If you
are going to be able to override a function variable then it definitely
NEEDS to be referred to from anywhere.

If the variable doesn't NEED to be available from anywhere then it shouldn't
be global.

There's also another class of globals in Delphi.  Hidden globals.  They are
globals which are declared only in the implementation section of a unit.
They are global to the unit, but invisible from outside the unit.  You might
have a TList which keeps track of instances of classes that you create.  eg:


interface
type
  TMyclass = class
   // cool stuff
    public
      constructor Create;
      destructor Destroy; override;
     end;

implementation


var
  MyClassList : TList;


  constructor TMyClass.create;
     begin
     inherited Create;
     if not assigned( MyClassList ) then
       MyClassList := TList.Create;
     MyClassList.Add( self )
     end;

  destructor  TMyClass.Destroy;
     begin
     if MyClassList.IndexOf(self ) >= 0 then
      MyClassList.Delete( MyClassList.IndexOf( self ));
     if MyClassList.Coujnt = 0 then
       FreeAndNil( MyClassList );
      inherited Destroy;
     end;


In this case the MyClassList is available to any part of the implementation
of the TMyClass.

Useful if you are using Window Regions or Window Hooks or a whole bunch of
things that I haven't  thought of.

In this case the MyClassList NEEDS to be made available to anything in the
implementation that uses it, therefore it should be global to the
implementation.  Otherwise forget global.  And if you need hidden global
like I've just described, then make sure it stays hidden.

My 2 cents, I hope that it helps someone

---------------------------------------------------------------------------
    New Zealand Delphi Users group - Delphi List - [EMAIL PROTECTED]
                  Website: http://www.delphi.org.nz
To UnSub, send email to: [EMAIL PROTECTED] 
with body of "unsubscribe delphi"

Reply via email to