As I update my POS, I’ve been creating four different types of layouts:
Interface layouts – for data entry and/or viewing data
Utility layouts – for new windows, loops, and other processes
Printed layouts – for generating reports
Developer layouts – for internal developer use only
Are there other types of layouts you regularly use in your apps?
Data API result layouts that contain the fields/portals you want to return in DAPI calls.
I have a set of layouts that I prefix with sys_, short for system. They have no layout objects on them and they correspond to table occurrences. They may be equivalent your utility layouts.
Steve, we also use blank layouts, either to improve performance within scripts or in some cases, no matter whether ‘Freeze Window’ has been set or not, we can get screen refreshes (in Windows) displaying a background working layout. In this case, we’d also use a blank layout set to the correct context and styled so as not to draw attention to it.
Blank layouts can be difficult to test and debug, so we’ll often put:
If [ not IsEmpty ($$DEBUG ) ]
Go to layout [ LayoutDisplayingFields ]
Go to layout [ BlankLayout]
Using Let to set or clear $$DEBUG makes it easy to toggle before the two.
We use the same procedure to format JSON if we’re debugging.
My typical set of layouts includes
- utility layouts with all the fields in a table
- blank layouts, 1 per table - no fields - for context switching, executing without the need to load any data field
- user layouts - data entry
- user layouts - reporting
- user layouts - utilities like FIND windows
- Card Window error dialog (no custom dialogs - more control this way)
- developer tools layouts, data cleansing, etc.
I’ve seen many solutions that include “all fields” layouts but I’ve always wonder what benefits they bring.
Typically for data quality / integrity purposes, using in the table/spreadsheet view mode to check things out. They only get used by developers.
I use the following:
- blank layouts, one per anchor (we use anchor-buoy);
- interface layouts for data viewing and entry;
- interface layouts for dialogues, pickers and similar UI elements;
- API layouts when needed;
- specialized layouts needed by scripts.
I used "all fields" layouts until I realized they impacted performance. They were seldom used. I now create and destroy such layouts only when needed. I sometime create troubleshooting files. They have these layouts and are not on the server.
ALL FIELD layouts have zero performance impact, IF you don't allow the users to use them or the developer to code using them. Their purpose is more around data, independent of code.
I use all-field layouts as developer layouts: to modify records manually - e.g. for testing purposes or to iron out errors caused by a bug - or to get an overview of whole records.
I name them this way: Basetablename_dev
I suggest leaving summary fields off all field layouts, otherwise you may be waiting a while after navigating to one of these. Particularly if your server is hosted on the Internet.
Summary fields are not a big performance issue, when the found set = 1 (or even a few). On a list view, they can be a performance nightmare.
when the found set = 1
We've found that they cause problems in layout mode.
And woe betide you if you accidentally go into a layout containing a summary field with a large data set. Time to go read War and Peace
I try not to make that [novice] design mistake in creating layouts. Same is true of unstored calc fields (of which a summary calc field is just one example). Even conditional formatting and HIDE characteristics are unstored calcs, although often (not always) lighter "weight" than data changes (no field write, just UI).
With prudent design, unstored calc fields can be eliminated by using an auto-enter calc with an embedded LET statement to trigger the calc programmatically, rather than the "always" that a typical unstored calc does.
We hardly use any calculation fields and never cross-table calculations. The vast majority is script driven, although the continuing lack of an OnRecordExit or OnRecordUnload script trigger continues to complicate this unnecessarily.
We avoid summary fields as much as possible and have a scripted alternative which still needs a bit more work.
All in the pursuit of performance.
Also worth noting that if you have 'Show Sample Data' set, then FMP will still draw down summary data when viewing a layout in Layout Mode, so I tend to restrict their placement to where only where they are explicitly needed, and in general, I'll try and script the generation of summary data, again, all in the pursuit of performance!
It is often a requirement to de-normalize child table fields in a parent, sometimes for performance, but also for the results of a FIND to be dependent on the parent only.
IF you have a child field on a layout and do a FIND against the field, the FIND results are based on the child, independent of the parent, typically providing unrelated records in the results. In a scripted find, you can resolve this by adding the primary key as an additional search term to the FIND, but in list view, it becomes a very complex FIND process. If the layout is based on the child, you have a similar problem with a FIND against the fields shown from the parent.
De-normalizing child fields into the parent, is almost always the most straightforward solution.
Using unstored fields to perform this, is a big performance issue. You can, instead, use an auto-enter field with a LET statement to set a calc-local variable, to some value that is guaranteed to change (I use a timestamp), which forced the auto-enter calc to trigger. A PSoS for a list of records, setting the timestamp trigger field, and therefore, causing the auto-enter to evaluate, lets you programmatically control when [what used to be unstored] auto-enter calc fields to update.