Sign in Join

Live chat for Free Pascal, Lazarus, Delphi and every Pascal programmer.

Mailing lists / lazarus / 2013-09

global items in TApplication

11 messages · 4 people · –

Reply by email Subscribe to this list Your subscription

Read-only archive. Use j and k to move between messages.

Marc Santhoff

Hi,

in the process of restructuring an old application I'm stuck on the question where to put globals. For example a global configuration object that has to be available in many units.

The problem ist:

- I cannot include the main program file (.lpr) in the "uses" clause, which means simple variables are not accessible.

- I cannot derive my own TApplication descendant because there is some magic behind the scenes working on TApplication directly (IIRC a constructor in the initialization part of forms.pp). This I'd like best, all globals (vars and references to objects) would be aggregated inside the application object.

In the past those globals where put as global vars inside the declaring unit and created in the initialization part, e.g. a TConfig is declared in unit config.pp and created on program start in config.pp, too.

The goal now is to have all global in the .dpr file of the program.

How do you handle this?
How can I meet the spec and put all global into the .dpr-file?

TIA,
Marc

Marc Santhoff

Reply by email

leledumbo
to Marc Santhoff

In short, you can't put it in the .dpr if you want it to be accessible from all units. Actually, there's not really any magic behind TApplication, you can still create your own TApplication descendant (preferably in its own unit) and assign that to Application variable. Provide a global property to access Application as your TApplication descendant to get its specific features.

However, I consider this approach complicated. If you don't like global vars, just provide getter function or read only property (property also works at unit level in fpc), let all those variables hidden in the implementation. A single unit that is set as application configuration is good enough.

View this message in context: http://free-pascal-lazarus.989080.n3.nabble.com/Lazarus-global-items-in-TApplication-tp4033337p4033338.html Sent from the Free Pascal - Lazarus mailing list .

Reply by email

Graeme Geldenhuys
to Marc Santhoff: in the process of restructuring an old application I'm stuck on the question where to put…
Marc Santhoff wrote
How do you handle this? How can I meet the spec and put all global into the .dpr-file?

I use the Singleton design pattern for the solution. I often create a Application Class (nothing to do with TApplication) that keeps track of such things like global user preference, lookup lists etc.

If other units require references I refactor my class structure so I have some base class I can pass in to other units. Those units then reference the passed in instance, and never the original application class (and related unit) directly. This is called Dependency Injection - yet another software design pattern that removes hard-coded dependencies.

Design Patterns are your friend! ;-)

Regards,
- Graeme -

fpGUI Toolkit - a cross-platform GUI toolkit using Free Pascal http://fpgui.sourceforge.net/

Reply by email

Graeme Geldenhuys
to Graeme Geldenhuys
Graeme Geldenhuys wrote
class (and related unit) directly. This is called Dependency Injection - yet another software design pattern that removes hard-coded dependencies.

I forgot to mention, using Interfaces are also immensely useful in this situation. Also makes it very easy to unit test such code.

Regards,
- Graeme -

fpGUI Toolkit - a cross-platform GUI toolkit using Free Pascal http://fpgui.sourceforge.net/

Reply by email

Marc Santhoff
to Graeme Geldenhuys: I use the Singleton design pattern for the solution. I often create a Application Class…
Graeme Geldenhuys wrote 17 lines
On 2013-09-15 04:22, Marc Santhoff wrote: > How do you handle this? > How can I meet the spec and put all global into the .dpr-file? I use the Singleton design pattern for the solution. I often create a Application Class (nothing to do with TApplication) that keeps track of such things like global user preference, lookup lists etc. If other units require references I refactor my class structure so I have some base class I can pass in to other units. Those units then reference the passed in instance, and never the original application class (and related unit) directly. This is called Dependency Injection - yet another software design pattern that removes hard-coded dependencies. Design Patterns are your friend! ;-)

It's not in question how to implement global objects. Some are singletons by design and others are not in code but work like they were, because the only place the constructor is (allowed to be) called is the inittialization section.

The qeustion is where to store those objects.

Marc Santhoff

Reply by email

Marc Santhoff
to leledumbo: In short, you can't put it in the .dpr if you want it to be accessible from all units.…
leledumbo wrote 6 lines
In short, you can't put it in the .dpr if you want it to be accessible from all units. Actually, there's not really any magic behind TApplication, you can still create your own TApplication descendant (preferably in its own unit) and assign that to Application variable. Provide a global property to access Application as your TApplication descendant to get its specific features.

I can, but then I'd have to choose one of two solutions I don't like: having to free the automatically created TApplication object or change forms.pp.

A single unit that is set as application configuration is good enough.

That's a god idea, one single globals unit but not having them in the main program source. Having all in one place is OK for programmes to get a quick overview and one spot where to look.

Thanks!

Marc Santhoff

Reply by email

Martin
to Marc Santhoff
Marc Santhoff wrote
I can, but then I'd have to choose one of two solutions I don't like: having to free the automatically created TApplication object or change forms.pp.

Create a descendant of TComponent, and have it owned by the application, that should take care of it

Reply by email

Martin
to Marc Santhoff: It's not in question how to implement global objects. Some are singletons by design and…
Marc Santhoff wrote 6 lines
It's not in question how to implement global objects. Some are singletons by design and others are not in code but work like they were, because the only place the constructor is (allowed to be) called is the inittialization section. The qeustion is where to store those objects.

1)

global war, but in implementation

interface
procedure GetFoo: TFoo;
property Foo read GetFoo;
implementation
var TheFoo: TFoo = nil;
procedure GetFoo: TFoo;
begin
   if TheFoo= nil then TheFoo:= TFoo.Create;
   REsult := TheFoo;
end;

Or, in the GetFoo

implementation
procedure GetFoo: TFoo;
const TheFoo: TFoo = nil;
begin
   if TheFoo= nil then TheFoo:= TFoo.Create;
   REsult := TheFoo;
end;

Reply by email

Marc Santhoff
to Martin: Create a descendant of TComponent, and have it owned by the application, that should take…
Martin wrote 7 lines
On 15/09/2013 15:24, Marc Santhoff wrote: > I can, but then I'd have to choose one of two solutions I don't like: > having to free the automatically created TApplication object or change > forms.pp. Create a descendant of TComponent, and have it owned by the application, that should take care of it

For having one class aggregating all other items, yes. Nice Idea, so construction and destruction will be handled cleanly.

:)

Marc Santhoff

Reply by email

Marc Santhoff
to Martin: 1) global war, but in implementation interface procedure GetFoo: TFoo; property Foo read…
Martin wrote 11 lines
On 15/09/2013 15:20, Marc Santhoff wrote: > It's not in question how to implement global objects. Some are > singletons by design and others are not in code but work like they were, > because the only place the constructor is (allowed to be) called is the > inittialization section. > > The qeustion is where to store those objects. 1) global war, but in implementation

^^^

I'm not willing to nuke the planet, yet. ;)
Maybe next time ...

Marc Santhoff

Reply by email

Graeme Geldenhuys
to Martin: 1) global war, but in implementation interface procedure GetFoo: TFoo; property Foo read…
Martin wrote
global war, but in implementation

Correct, or just use a "lazyman's singleton" function.

----8<-------------8<-------------8<-------------8<-------------8<----

interface
function GlobalFoo: TFoo;
implementation
var
  uFoo: TFoo;
function GlobalFoo: TFoo;
begin
   if uFoo = nil then
     uFoo := TFoo.Create;
   Result := uFoo;
end;
initialization
  uFoo := nil;
finalization
  uFroo.Free;

----8<-------------8<-------------8<-------------8<-------------8<----

Regards,
- Graeme -

fpGUI Toolkit - a cross-platform GUI toolkit using Free Pascal http://fpgui.sourceforge.net/

Reply by email