Jump to content
Mike Torrettinni

Is it really good practice to create Forms only as needed? Always?

Recommended Posts

In previous thread David said: " Don't use a global variable for each form. Remove them. Use a local variable and destroy it when ShowModal returns.  "

 

So, good practice is to create Forms as needed and destroy after closing. But are there any cases where this practice doesn't apply?

I have numerous forms, some are just custom dialog boxes, with a few controls, some are settings forms, where up to 50+ settings can be set (label + edit + tabs). Especially for these Settings related screens, the logic says: create once, use for the life of application and all the values that developer set once, will be there until closing. So, why would I need to recreate every time someone looks at settings, and go through the whole procedure of filling up the settings on the screen, translating the screen local language (if needed)... and so on.

 

So, I thought maybe it's the memory consumption. With my quick test of around 60 forms, here is the memory consumption:

 

Creating all forms at start:

image.png.21977da99665574c1d2a76d9acaabf2c.png

 

Creating only Main form at start:

image.png.56f7af017e90715986fccacab00861b7.png

 

At least for my case, the difference in memory consumption is negligible.

 

I'm just trying to understand a bit more, before I start changing everything for the sake of 'good practice'.

 

Share this post


Link to post

It's not about the memory. It's about removing global variables that allow form instances to poke at each other's internals. It's analogous to making fields private rather than public. 

 

Those form variables only exist because in Delphi 1 the designers were trying to ape functionality of VB.

Edited by David Heffernan
  • Like 4

Share this post


Link to post

... in addition to David's comment.

 

If you have plenty of forms, all created at the begin, your Startup-Time is looooong!

Share this post


Link to post

I can tell you, if our application was creating all of its gui at startup, hell would freeze over. And your systemresources, too.

The ugly thing is, Memory is not what will kill your application. The handle limit will! There is a GDI-handle limit(in addition to others) you'll run into.

Edited by Memnarch
  • Like 4

Share this post


Link to post
2 hours ago, ConstantGardener said:

If you have plenty of forms, all created at the begin, your Startup-Time is looooong!

You're right. A better solution would be to create and initialize a form by request, and then Show(ShowModal)/Close it as needed. The reference to the created form can be saved as a class variable and freed when an application to finish. It makes sense for forms that need to maintain their state. Or for modal dialogs. And you need to ensure that two or more identical forms are not opened at the same time.

Edited by Kryvich

Share this post


Link to post
5 minutes ago, Kryvich said:

[...] The reference to the created form can be saved as a class variable and freed when an application to finish [...]

Only do this for Forms/Dialogs/UI that is used VERY frequently and as a huge impact when created for the first time. Consider saving a state in Dataobjects somewhere else otherwhise, if needed.

Edited by Memnarch

Share this post


Link to post
2 hours ago, ConstantGardener said:

... in addition to David's comment.

 

If you have plenty of forms, all created at the begin, your Startup-Time is looooong!

If the creation of plenty forms take too long, then you are doing something wrong. The creation of the instance itself should be very fast, but a lot devs run some lengthy initialization code inside the form constructor which is a bad practice.

 

The only point that matters is the global variable we should get rid of

Share this post


Link to post
9 hours ago, Mike Torrettinni said:

Settings related screens, the logic says: create once, use for the life of application and all the values that developer set once, will be there until closing.

For these cases I prefer moving the settings to a separate settings class independent from the settings form. Then I can create and initialize an instance of this settings class at startup, load the settings from some storage and adjust with some command line parameters. Then the settings are available all over the application without having to rely on the settings form creation. I often have the case where I need access to the settings long before the main form is created. This would be hard to achieve using the settings form as the central storage for the settings.

  • Like 5

Share this post


Link to post
27 minutes ago, Uwe Raabe said:

using the settings form as the central storage for the settings

Is an anti pattern to me -> mixup of UI and logic

  • Like 2

Share this post


Link to post

You don't need to keep forms alive to preserve settings because you don't store setting in form instances. You store them elsewhere. 

Share this post


Link to post

Well, this whole thing started with moving settings into their own container. Then I started looking into startup time. For some reason my startup time was 8s, after a couple of days of blaming creating all Forms on start, I figured out it was exception handling tool, removing it saved me 5s - the different one doesn't add any time to startup.

So, while all these big changes, I needed a quick solution to delay creating Forms, which was actually not the cause of delayed startup. But now I'm here, so can't go back and need to find a middle ground of what I used to do, what I know now, what will eventually be and the most important what I can do now in short time for best results and not breaking anything 🙂

Share this post


Link to post
4 hours ago, Memnarch said:

The ugly thing is, Memory is not what will kill your application. The handle limit will! There is a GDI-handle limit(in addition to others) you'll run into.

This makes sense! I do have a lot of of controls in my whole application. And now some of the issues, odd errors pointing at controls code which I was never able to replicate and fix... could makes some sense.

 

If ComponentCount shows count of Main form controls, then I have 3000+ controls(components) on Main form... on various page controls. Not sure if this is a lot or not.

Share this post


Link to post
5 minutes ago, Mike Torrettinni said:

I have 3000+ controls(components) on Main form...

I never see such forms. Is it for flight control center?

Share this post


Link to post
1 minute ago, Kryvich said:

I never see such forms. Is it for flight control center?

No... it's actually very simple (looks wise) reporting tool, but organized into 50+ separate tabs (features) on page control(s). So, not cluttered, but all on Main form... I only use Frames for 1 feature. I like to have all in 1 place, I guess.

Share this post


Link to post
27 minutes ago, Mike Torrettinni said:

This makes sense! I do have a lot of of controls in my whole application. And now some of the issues, odd errors pointing at controls code which I was never able to replicate and fix... could makes some sense.

 

If ComponentCount shows count of Main form controls, then I have 3000+ controls(components) on Main form... on various page controls. Not sure if this is a lot or not.

Doesn't sound like resource exhaustion is to blame. More likely plain defects in your code. 

Share this post


Link to post
3 hours ago, Schokohase said:

Is an anti pattern to me -> mixup of UI and logic

Yes, but it has(had) it's benefits for my case, I could set all default values directly on the forms, which was great.. until now, when I had to separate UI and logic. So, the form creation always needs to read these settings and set the controls, every time the form is created.

This is where I still have dilema between constanlty generating form, or maybe find the most common used ones and have these as globals, and the rest as local create, use, destroy Form type.

Share this post


Link to post
2 hours ago, Mike Torrettinni said:

No... it's actually very simple (looks wise) reporting tool, but organized into 50+ separate tabs (features) on page control(s). So, not cluttered, but all on Main form...

I presume you didn't put all that controls to the form manually. It's a lot of work. I would use some sort of automation, and create  the appropriate controls on the fly when the tab was selected. Then you'll get 3000/50 = 60 controls at a moment.

Share this post


Link to post
48 minutes ago, Kryvich said:

I presume you didn't put all that controls to the form manually. It's a lot of work. I would use some sort of automation, and create  the appropriate controls on the fly when the tab was selected. Then you'll get 3000/50 = 60 controls at a moment.

Of course, all manually. Except for obscure cases, I haven't had the need to create controls on the fly - IMHO this goes against Delphi RAD...  of course, each feature/report on it's own Tab control and over the years it grew to 50+ tabs (features/reports).

Do you create Forms, controls on the fly? For what benefit, what is real life scenario?

Share this post


Link to post

Have you measured how users work with your program? It's possible that an average user use 5-10 reports (tabs) in one session. Then all controls on other tabs just sit in memory, grab GDI resources without need.

 

It's OK to create the form layouts manually, Delphi has all instruments to make this work easier. But after rising HTML and CSS it has become fashionable to entrust the program with the placement and adjustment of the size of controls on a form. For ex.

 

Edited by Kryvich

Share this post


Link to post

Generally speaking, I don't auto-create any forms that aren't required to be around for the entire duration of the program's execution.

 

So there's the Main form, any DataModules that are used by other forms (bad practice, but very common), and any other forms that are simply easier to leave around to hang onto values that would otherwise need to be saved somewhere else.

 

Everything else is created as-needed and freed when I'm done using it.

 

As far as your 50-tabbed notebook ... it must take forever to open that form in Delphi!

 

At some point, I'd change that from a tabbed notebook to a panel where I loaded up an embedded form (created on-the-fly) from a combobox selection.

  • Thanks 1

Share this post


Link to post
54 minutes ago, David Schwartz said:

As far as your 50-tabbed notebook ... it must take forever to open that form in Delphi! 

 

At some point, I'd change that from a tabbed notebook to a panel where I loaded up an embedded form (created on-the-fly) from a combobox selection.

Yes, it takes longest, about 6s to open a project and main form to appear and is ready. Other projects are much faster, but 6s opening project is not something I'm concerned about. It's more a concern that it takes FormCreate 0.5s, which is a bit too long, but still not a real concern, at this moment.

 

Imagine... could it take only 1h-2h to split each tab into a Form.., then test and fix little issues... around 4h per tab? x50 = 200h... I don't see how I can squeeze 200h into current timeline, at this moment. Unless you have a suggestion how to do it 1 day or 2?

Share this post


Link to post
1 hour ago, Mike Torrettinni said:

Yes, it takes longest, about 6s to open a project and main form to appear and is ready. Other projects are much faster, but 6s opening project is not something I'm concerned about. It's more a concern that it takes FormCreate 0.5s, which is a bit too long, but still not a real concern, at this moment.

 

Imagine... could it take only 1h-2h to split each tab into a Form.., then test and fix little issues... around 4h per tab? x50 = 200h... I don't see how I can squeeze 200h into current timeline, at this moment. Unless you have a suggestion how to do it 1 day or 2?

Well ... I'd think more like 5 minutes per tab to copy the components into a new form. Then you need to figure out how you're going to get the data in and out, which should be the same for all of your forms (just for consistency sake).

 

So the first four might take an hour. But after they, they'll go steadily quicker, maybe 10 minutes each.

 

Watch my CodeRage 9 video for more insights:

 

Share this post


Link to post

Create an account or sign in to comment

You need to be a member in order to leave a comment

Create an account

Sign up for a new account in our community. It's easy!

Register a new account

Sign in

Already have an account? Sign in here.

Sign In Now

×