Did you know that... [globals part1]

Document created by Cécile on Jun 8, 2018Last modified by Cécile on Jun 10, 2018
Version 7Show Document
  • View in full screen mode

 

Ever since I read the Advanced Training Series, globals have been a source of anxiety for me!

I recently had to use them extensively and just doing some copycat scripting and field definition would not cut it.

Since fear mostly comes from the unknown, I decided to get to know the beast!

 

What helps making the topic confusing is that they are used in various types of strategies (I don't have an exhaustive list of them {yet?}) and for each strategy, the definition of the field and the scripting are different. Moreover, globals behave differently if their content is set by client interaction or through the uploading of the file. I also didn't understand why people would recommand using them to set a value in a field, when that field should be different for every record yet the global being... global. common to all records... I simply coudn't wrap my head around this (and I still have a few ??).

 

When you are a beginner, you are faced with three challenges: you do not know what you do not know, you most likely do not have the trade's vocabulary to research what you are trying to do and, even if someone tells you which strategy to apply, you will most likely not know how to write/script that properly because you don't know how to do that either! If you are expecting a way to overcome all that, well there is, but it is no magic pill. It is practice, practice and practice. In my case, I hate to exercise so I try to sneak it in other activities. For example, I bike to work.

 

With programming, it is the same thing. I can't sit in a classroom. So I take little projects and learn while doing. I recently had a project that forced me to get a better grasp on globals. So here is your project:

 

"In your system, you want to have a layout where you can go and set your system preferences and parameters; among which the current tax rate. That rate might change from year to year, therefore you want to be able to go to that place and change the value entered so that from that point on, all the invoices you make will use the new rate. Of course, you do not want last year's invoices recalculated with the new tax rate! Just set for new invoices from that point forward."

 

Given our problem, we already know that a tax rate will be a value that will appear on all invoices and, aside from yearly adjustement to the rate, the value will always be the same. We know that we need in our invoice layout some place to hold that value which will always be the same, and will be used to calculate the taxes and, ultimately, the Grand Total of the invoice. Therefore, we can intuit that the tax rate is some sort of global field because it is common to every record. However, we also know that eventhough it will be the same for large sequences of invoices, it is possible that the rate changes over time and that future invoices need to bear a different tax rate. In this case, if the field is global, the moment we adjust to the new rate, all invoices will now bear the new rate, including past invoices. That seems a problem.

 

Before we decide which strategy we are going to use, we need to understand more about globals.

 

First the mechanism:

We will examine the global fields that store constant values (hereinafter "gcv") vs the global field that hold values destined to vary (hereinafter "g"). Note that developers do not make a distinction and usually prefix global fields name with only a lowercap g (which amplifies our beginner's confusion when reading a file). I will make the distinction in this article to keep things compartimented for now.

 

To work with a gcv:

When working with a global, especially a gcv, one can assume (wrong) that since the value will be the same for all records, when defining the global field, it suffice to check the autoenter option "data" and set it to "somevalue". NO. Unless there is at least one record in the table that contains a global field, that value has not left your wishlist to digitally inhabit a field and therefore it will not get a real shot at life. See comments 1 & 2 in this thread for more information about how a value can be set to your global field.

handshake.png

 

Many developers like to put their gcv in what they call a "utility" table, only seen by the developer. One particularity of globals in general is that they can be used anywhere in the solution, even if they are not in a table related to the table a layout is based on. So a utility table where one keep the globals may be practical for maintenance purpose.

 

What makes your global a gcv is how you set its value AND whether the solution is hosted on a server or locally.

I created a test file to demonstrate how this work:

 

Before we dig in, because the field type matters, if you are still a bit unsure about how and why setting a field type and its options, I recommand that you read Did you know that... [field types]  a post I wrote about choosing the right type of field and using fields options purposefully.

 

Now that you understand well field types and what indexed fields are, I can address the issue we found earlier about using a global field for our tax rate (See the orange text above). Since a global field value would be the same for all invoices, past, present and future, if you change it in one field, it would affect all the history by updating the old invoices calculations. I can guarantee your accountant will kill you if you do that.

 

What we want is all invoices to have their tax rate field set to a taxrate value that will remain frozen in time. That sounds like an indexed field doesn't it? Indeed. Now, since we are lazy by nature, we do not want to have to type that tax rate over and over on each invoice we will make, especially because that rate will likely be the same for months and years at the time. You see where I am going, I 2018-06-07_13-58-40.pnghope! If not, look at the two tables to the left: you have in Invoice a TaxRate field. It is a number field INDEXED with the auto enter set to calculated value = gTaxRate and the option "do not modify existing value if any" CHECKED.

 

What that will do is, when you will create a new record, the field tax rate will sets itself to the gTaxRate value. If, in the future you change gTaxRate, the rate in the record will not change, because you have set the field's option to "do not modify existing value, if any".

2hicken-wing-clipart-clipart-panda-free-clipart-images-AqrSeD-clipart.jpg

 

As you can see, I have 2 tables, one which will hold my records fields and one "utility" with my global field.

There are no relationships between these tables.

Yet, that will not be an issue because global fields can show up to any party you want since they do not need to be related.

 

 

2018-06-07_13-58-16.png

This is my invoice layout based on Invoice table. You have the Invoice table fields on the left and the global field from the TestGlobals table on the right. The Left fields are local to the table "Invoice" but the global field on the right is from another table so its full name is referenced (note the :: before the field name). I have put the global field on this layout for our convenience to see what happens.

 

I created one record in the TestGlobals table and put the value ,05 in the global field.

2018-06-07_14-06-59.pngThe field "TaxRate" is a number type of field, set to autoenter, option Calculated value = TestGlobals::gTaxRate and the box do not change value if any is checked.

The field "Grand total" is a calculation type of field; the calculation is = Subtotal+ Subtotal*TaxRate.

 

 

Context 1: the file is open by a self standing copy of FMPAdvance 17 installed on the user's computer. (LOCAL)

  1. I created a new record in the Invoice table. The TaxRate number got set automatically. 2018-06-07_14-09-06.png
  2. I manually typed in the subtotal so the GrandTotal automatically updated.
  3. I closed the file.
  4. Upon opening the file again, this is what I have:

To a beginner's eyes. That looks ok and normal. Although at this stage, anything that doesn't go in eternal loop or doesn't crash or worst - do NOTHING - would look normal anyway...

 

     5. I change the value in the global field to ,03. The value does not update in TaxRate field because I changed the global value AFTER that record was created. This is consistant with the field definition which is in2018-06-07_14-12-15.pngdexed so it would not update unless I told it to do so (well with a script; although I often talk to my computer, it rarely responds) AND if the box "do not change value if any was UNchecked. But we made sure it is checked so our past invoices will remain impervious to any government tax whim.

 

 

6. Now, I close the app. When I reopen it, I have the same exact scenary. So the value I put in the global field remains the new value I input. In other words, it keeps the last value it has been set to.

7. Let's create a new record: the new record autoenters the current gTaxRate. That really looks good an normal.

2018-06-09_20-45-27.png

So in our Context one, the file opened locally, our global field is a a gcv. It retains its value when you close the file.

 

 

 

Context 2. The file is hosted on a server and accessed remotely from a FMPA client. (HOSTED solution)

In this context, you need an additional piece of information to understand what is about to happen. When the file was uploaded to the server, there was one record in the table TestGlobals and in that record's gTaxRate field, there was a value (,05).

 

1. I open the hosted file: o2018-06-07_14-13-09.pngk record ID 2 in the Invoice table looks the same.

2. I change the gTaxRate to ,04

2018-06-07_14-15-41.pngLike in Context 1, the existing record is not affected. Which is indeed the expected behaviour.

 

3. So we venture and create a new record:2018-06-09_21-12-48.png

 

 

Again, this is the expected result. Ok everything works good.

Let's remove the gTaxRate field from this layout and put it back on its own layout. It was there only for demonstration purpose. And make our Invoice layout more cute and realistic.

 

2018-06-09_21-31-13.png

So here is our final design. The TaxRate field has been formatted in percentage, the fields Deposit and Discount (Ajustement) have been added. Looks good and ready to deliver, right?

 

When your client will open the file from her desktop, she will be all happy to see this and right away, she will start creating new invoices. And here is what will happened.

 

2018-06-09_21-41-07.png

When she creates a new invoice, instead of the 4% tax rate, the field sets itself to 5%.

 

So you go to the TestGlobals layout and discover that the rate in the field is

 

2018-06-09_21-45-59.png

Thinking, that's odd, "I'm sure I had set it to ,04..." You tell her to set that field and, happily, for the remainder of the day, she will invoice all her clients with the right tax rate. The next morning, she doesn't even remember the incident and starts billing people until noon when a customer makes her notice that on the invoice she has sent him, the tax rate was wrong. Embarassed, she fixes the issue with all the morning customers and call you rather unimpressed.

 

What happened?

Global fields, like global variables, are "user and session specific". If you open a file with FMPA on your computer, the values you set in the global fields will remain constant every time you open the file. It will remain ALSO constant to people who remotely access the file if you share it. They will be able, during a session, to have their own computer/FMPA (client) set and use different values in those global fields but once their session ends, the values revert to the value they were/are set to on the hosting computer/FMPA app. Therefore, the next time they connect to the database, the values they will see in the global fields will be those from the hosted file, not the ones they had set at their last session.Of course, any record's indexed fields' value the user would have modified will have retained its value. That is also true for indexed fields which value is set by interacting with a global: when, during a session, a remote client runs a script that changes the value of a global and then sets the value of an indexed field based on that global, the indexed field will retain the value it acquired. The global's value however, when the file is reopened, will be reverted to what it was when the file was last uploaded to the server. That is why your client's first day invoices were still correct the next day when she opened the file again but why the new ones were wrong: the global which sets the tax rate rate field value in the invoice table had reverted to its constant value.

 

Let's figure out where you got tricked. When you uploaded the file to the FileMaker Server, the value that was in the gTaxRate field was ,05.  Then you continued developing, eventually setting the tax rate to ,04, assuming that you had set all parameters right for your client to start using her solution.

 

But in reality, the moment you uploaded the file to the server, it was closed on your computer and reopened on the server frozen in time with the values that were in the fields at the moment of upload. When you reopened the file, seemlessly, you had become a remote client, therefore, any change in global variables or fields that you would make would only be session specific. If you want the TaxRate value to always be ,04, you have to reopload the file, with the values you want constant.

 

There is an alternative to reoploading the file with different values that you want to remain constant in global fields (which is not always possible or desirable on a practical standpoint especially for businesses that can't suffer much downtime or huge databases).

 

You create a script triggered on first window open, to initialize all your global fields and global variables. That is what is commonly done.

 

In the second part of this topic, I will discuss when it is worth uploading a value with the file, usually as part of a maintenance process and when it is best to use session based initialization of the fields and variables.

 

We will also continue to discover the proper strategy to provide your client with a solution that does what it needs to do!

 

À plus!

 

Cliparts credits: lisa boudreaux on clker.com (chicken) and ocal on clker.com (cat&dog shaking hands), mariafresa.net (Chicken Wing Cartoon Clipart #1867733)

4 people found this helpful

Attachments

    Outcomes