What do we have in Common?
One of our colleagues asked a good question in a forum yesterday about when to use UnNamed Common vs Named Common in Pick BASIC programs. I thought this would be a good opportunity to post some detailed information to the MV category here in the blog so that everyone could see it.
>The more I think about it how could your Common,
>named or otherwise, get tangled with another suite?
>Sorry I can’t see that. If I logon as Thomas and you
>log on as Ross then our unnamed Commons are
>separate. If we both run a program with Named
>Common then those two sets of the same name are
I’ll address the multi-user question first and use that as a lead into Named Common vs UnNamed Common.
The assumption here is that only one person is using a given MV process via telnet or serial cable – two users means two ports, and that’s two sets of Common, Named or not. While some GUI development these days (using UniObjects, D3 Class Library, and some proprietary interfaces…) still dedicates one user per connection, most of us doing some sort of remote connectivity are using an MV connection simply as a convenient method for any user to access the database. I believe all non-MV databases support non-persistent connections as the preferred and default method, and while discouraged from doing so, some developers regard persistence as the unusual connection method that they might like to use as a rare option.
We Pickies expect "state" to be managed in the DBMS, and to do otherwise is unusual and downright silly to those who have been writing MV code for so many years. But we are coming in from the outside now, and to avoid the pain of doing a login on every request for data, we keep it connected, and then manage access to these connected ports through pooling mechanisms of our own design. Each connection maintains state for the connectivity tool via Named Common – state is rarely preserved for individual users at this connection point. Examples of data to keep "in state" like this include handles to temp files for managing lists, locks, or commonly used UI elements.
Again, that state is just for the Connectivity tool. Often the connectivity tool was not created by the same people who wrote the application, so app developers need their own Named Common for app file handles, etc. This is not for individual users because from one second to the next any given user could be jumping around among many MV ports, and many users could be alternating use on any given port. The user state is being maintained in the middle tier or in the client, not on the back-end like a telnet session.
To Name or not to Name … Common that is…
To take it one step further, app developers might be making use of coding tools that make use of Common for their own purposes – that would have to be Named Common. Consider the fiasco if every tool created by every company used UnNamed Common which relies on variables in different programs to be positioned in a specific location in order to be shared. Let’s have a quick look at some code:
COMMON CONN.TEMPFILE1, CONN.LISTFILE1
COMMON APP.TEMPFILE1, APP.LISTFILE1
Any time you made a change to your business application you would need to re-compile all of the tools you use in addition to all of your app programs. Why? According to the above code, the Email tool is expecting its data in the fifth position. If you add a variable to the first line then the Email tool won’t find its data in the fifth position because its data has now shifted into the sixth position. So you need to re-compile the code for the Email tool so that it knows that you have five other common elements before the one it needs Since you probably don’t have the source for many tools you purchase, changing this would be impossible.
With Named Common we can make use of different blocks of common for different purposes, without regard for which position someone used in their own unrelated component. Tool vendors frequently provide a common block for you to use in your own code, in order to allow your code to properly flow data with their code. So you can do something like this:
COMMON /CONNECTIVITY/ CONN.TEMPFILE1, CONN.LISTFILE1
COMMON /MY.APP/ APP.TEMPFILE1, APP.LISTFILE1
COMMON /EMAIL.CORP/ EMAIL.TOOL.VAR1
COMMON A1, B1, C1
Now you can modify your Named and UnNamed common without affecting or needing to change anyone else’s code. The above could just as easily have been written as follows:
COMMON /MY.APP/ APP.TEMPFILE1, APP.LISTFILE1
COMMON A1, B1, C1
The change in order won’t affect any programs that interact with this program. The Include statements remove the possiblity of someone accidentally messing up the common lines. Further, if you get a new version of one of the other products, you don’t need to change any of your code, you just need to recompile in order to get your code to recognize the new location of the variables in the third-party common blocks.
OK, so we have covered why we use Named Common for connectivity and third-party tools. But when would we choose Named Common or UnNamed Common for our own code?
One reason to use Named common is that you might be jumping around various programs that may or may not share the same common blocks. For example:
Program1 is a part of the application and includes COMMON a,b,c.
Program1 calls to Program2, maybe for email. These don’t need to be third-party tools and you might have all of the source. Program2 doesn’t need to know anything about the application so it doesn’t include a COMMON a,b,c line, but let’s say this Program2 calls to other email-related programs to provide mail server details. So Program2 has its own COMMON a,b,c,d,.
The first thing we notice is that Program1 has 3 arguments and Program2 has 4, so as soon as we call from Program1 to Program2, it’s going to abort, warning us that we’re missing an argument. Clearly we don’t want to modify the email code and its related programs every time we make a change to our application software.
Another thing to note is that even if both programs had the same number of arguments, Program1 variable "a", maybe for "accounting" purposes, probably shouldn’t be passed into Program2 where variable "a" might be an "address" for sending email.
The solution is for Program1 and other app-related programs to use Named Common: COMMON /APP/ a,b,c, and for Program2 and other email programs to use their own: COMMON /EMAIL/ a,b,c,d.
Named Common is significantly different from UnNamed common in that the data is persisted on the DBMS session even if all programs stop running and control is returned to a menu or even the command line. Any program that starts up will have access to the common blocks. UnNamed common disappears when all programs exit from the BASIC runtime, or when a Chain or Execute is done to a program set with completely different common definitions.
Depending on which MV platform you use, and the topic of heated discussions, you will also find that Named Common persists across a Logto into other accounts. This can be a "feature" if you move from one account to another to retrieve and manipulate data, and you don’t want to re-initialize your variable space just because you’re going somewhere else to get data. It has also been called (among other colorful terms) a bug and a problem waiting to happen. Consider that if you open files in the local account/database, storing the handles to these files in Named Common, then you move to another account. Your code checks to see if common has been initialized. It has, so you don’t need to do it again as you would with a new login. So you read and write data when you’re in the new account. But the file handles are still pointing to the other database. This can create some nasty data inconsistencies for the unwary.
We’ve seen why we may or may not want to persist specific kinds of data, and we’ve covered a few scenarios for when you might choose one type of Common over another. I hope that’s helped some people who have wondered what this Common stuff is, and maybe some of you who thought you knew all there was to know about it. I intentionally haven’t covered absolutely every aspect or nuance. I wanted to give you enough information to go back to your platform-specific documentation to get more details which should now make just a little more sense to you. If I’ve left out major considerations, I’ll be happy to write another blog on the topic.