1. Dan Cooperstock
  2. PowerBuilder
  3. Thursday, 31 October 2019 16:33 PM UTC

We have a common PBL (common.pbl) that is used by three different applications. Each application declares some global variables of types of user objects in the common PBL. 

Objects in the common PBL need access to some of those same global variables, so our design was that they get injected into the objects with of_initialize functions (for user objects) or as PowerObjectParms with OpenWithParm for windows. 

So for instance one of the global variables that instantiates a common PBL object is called gMsg (a custom messagebox). To inject it into a window in the common PBL, we would OpenWithParm(windowName, gMsg), and in the window, declare an instance variable iMsg of the same type, and in the Open event, do iMsg = Message.PowerObjectParm. Then whenever we need that in that window, just use iMsg.

We did that because we compile the common PBL separately (so each app doesn't always have to do so), using a separate tiny common application PBL (commonapp.pbl). The application object common.sra in commonapp.pbl doesn’t contain declarations of the same global variables. So commonapp.pbl and common.pbl together wouldn't compile if any objects in common.pbl referred directly to the main applications' global variables.

Then we use only common.pbd, compiled as above, in each of the three real applications. (Commonapp.pbl is only used for the separate compilation of common.pbl.)

But it just occurred to me that I can declare global variables in common.sra using the same names and data types as the individual application's application objects do - such as gMsg mentioned above. Then all other objects in commonapp.pbl could just refer to the global variables by their normal names, and it would work whether for compiling commonapp.pbl along with common.pbl separately, or when using common.pbd as part of the actual applications.

Does anyone see any problem with this change, like reasons why the global variables with the same names in the application object in commonapp.pbl and the real applications' application objects would not be seen as being the same?

Thanks.

Dan Cooperstock Accepted Answer Pending Moderation
  1. Monday, 18 November 2019 00:52 AM UTC
  2. PowerBuilder
  3. # 1
1
Votes
Undo

FYI if anyone is interested what I was suggesting in the original post - getting rid of the injection of globals in our common PBL by instead declaring those same globals in the common application object we use to compile the common PBL separately - worked perfectly. That allowed us to greatly simplify a lot of code.

Using the TopWiz Software PBSearch tool also greatly sped up all of the related changes. As well as including global search and replace through entire applications, it will even check out objects that aren't yet checked out from your source control system, before making those changes.

Comment
Happy to hear you found workable solution!
  1. Michael Kramer
  2. Monday, 18 November 2019 05:44 AM UTC
There are no comments made yet.
Miguel Leeuwe Accepted Answer Pending Moderation
  1. Saturday, 2 November 2019 06:04 AM UTC
  2. PowerBuilder
  3. # 2
0
Votes
Undo

I do encapsulate most global stuff in nvo's but let's be honest: Lots of time we then end up declaring these nvo's as global objects. Like for example the gnv_app object from the pfc's and if I'm not wrong there's similar declarations with Chris' STD classes.

So in the end .. it's still all "kinda global" isn't it? Also, for functionality which you use all the time everywhere, that's the correct way of doing it in my opinion. You're not going to create and destroy an nvo all time for each and every method you might use, like for which a Messagebox would be a good example.

regards from "bad programmer" :)

Comment
There are no comments made yet.
Miguel Leeuwe Accepted Answer Pending Moderation
  1. Saturday, 2 November 2019 05:52 AM UTC
  2. PowerBuilder
  3. # 3
0
Votes
Undo

I have not enough knowledge about variable positions and stuff to give you a good answer but have used common pbls in the past. So this is just out of interest.

Maybe I'm missing something, but "why use a pbd in the first place?". Why not simply hookup the common.pbl in all of the applications that need it?

That way you can just use the globals from the applications, no need for injection and have no need to compile the common libraries separately with the 'tiny' application.

The only thing is that after building, you have to deploy the .pbd / .dll's of the common libraries in separate folders (like adding them to the individual applications' folder. I've done this when using pb 6.5.1 with a developer team of around 80 people and never had any problems.

Comment
The advantage that I see of compiling the common PBL separately to a PBD is that it doesn't change that often, so compiling it separately when it does change saves some time on the compiles of our three applications that just use the PBD. We do already have each of our PBL's (including the common one) in a separate folder.

Thanks.
  1. Dan Cooperstock
  2. Saturday, 2 November 2019 12:18 PM UTC
True, you´d win some time. That makes me wonder how much time I´d win on adding my pfc pbl´s as pbd´s (not the pfe's, as we do want to be able to at least debug those all the time). I guess I'll give it a try.

regards
  1. Miguel Leeuwe
  2. Saturday, 2 November 2019 12:26 PM UTC
There are no comments made yet.
Michael Kramer Accepted Answer Pending Moderation
  1. Friday, 1 November 2019 08:31 AM UTC
  2. PowerBuilder
  3. # 4
0
Votes
Undo

I agree: minimize global variable use.

I prefer dependency injection to global references any day of the week.

This (always?) increases testability among other preferred traits. So stick to your habit. It is a very good habit!

HTH /Michael 

Comment
Here's the thing. Each of our three apps has about 5 PBLs, only one of which is the shared common PBL. All of the other PBLs use the global variables, with no dependency injection. We are definitely not going to change that!



The question I asked (which basically nobody has answered, preferring to offer their philosophies on the use of global variables, which I did not ask for!) is whether using those same global variables in the shared PBL, which is usually used as a PBD, will cause any problems, as long as we declare the same variables in the application object of the small PBL we use for compiling the shared one.



If anyone has specific answers about that actual question I asked I would be glad to hear them. As I have said in one previous reply, a very minimal test of such a change seems to have worked fine, but I'm looking for your knowledge about whether there's anything I'm missing that would cause it not to work (outside of philosophical objections).



Thank you.
  1. Dan Cooperstock
  2. Friday, 1 November 2019 12:09 PM UTC
Hi Dan,

I wouldn't convert existing code that works fine. Code that remains static has less risk of sudden failure than code often modified.

My learnings with PowerScript >

A) IF - your shared .PBD code references any global variable - THEN - Keep "globals" list identical (types + order) across apps to increase success rate. - PERIOD.

B) "Globals" = 5 x standard global (SQLCA, etc) + your explicit global variables. Every app defines the standard variables before first "global variable" so type difference in any standard variable may alter memory positions of your explicit globals and render your shared .PBD erroneous in at least one app.

My recommendations >

1) Keep your shared .PBD as independent of any globals as practically feasible to minimize risk when reusing.

2) Inject references to any global as function arguments -- EX: Pass SQLCA as argument to a setter for an instance variable.

3) Avoid direct access to Message object's properties in your shared .PBD.

4) Test for safe .PBD sharing before any code release.

You may have less inherent risk in your app port folio than I often see. I still recommend dependency injection to globals dependency.
  1. Michael Kramer
  2. Friday, 1 November 2019 18:30 PM UTC
Short answer >>> Shared .PBD can be rendered useless for an app by: A) Standard globals declared differently. B) Global variables declared differently. C) DW object used by shared .PBD implemented differently. D) Any ancestor class to shared .PBD implemented differently.

Mitigate any such risk by keeping shared .PBD code self-contained and avoid duplicate names for classes and DW objects.

HTH /Michael
  1. Michael Kramer
  2. Friday, 1 November 2019 23:58 PM UTC
There are no comments made yet.
Chris Pollach @Appeon Accepted Answer Pending Moderation
  1. Thursday, 31 October 2019 18:59 PM UTC
  2. PowerBuilder
  3. # 5
0
Votes
Undo

Hi Roland;

  I agree 100% ... avoid Global Variables!

Regards ... Chris

Comment
Fine, but that's not going to happen in our code, as it would be a MASSIVE re-write of something that is working fine. But if I can get rid of all of the injection of those globals into NVOs and windows in our common PBL that would be worth doing, to simplify the code and also prevent certain types of bugs we encounter when the injection isn't done right.
  1. Dan Cooperstock
  2. Thursday, 31 October 2019 19:05 PM UTC
Global variables are fine for something that is globally used in the application. If these are NVOs that's fine too.

I think that it is ridiculous to write loads of code to work round the fact that you do not want to declare a global variable.

I think that issue is trying to use PBDs as part of the source, I would recommend compiling the application from the complete source. To say that you can save a little time building the exe file is somewhat irrelevant really. We fire off a compile which is done automatically on our build machine if that takes 30 seconds longer it really does not matter. Especially when it means that you application runs without any issues and coding is simpler.... Surely these are more of a priority than saving compile time?
  1. David Peace (Powersoft "The PowerBuilder & C# People")
  2. Monday, 18 November 2019 14:45 PM UTC
There are no comments made yet.
Roland Smith Accepted Answer Pending Moderation
  1. Thursday, 31 October 2019 17:42 PM UTC
  2. PowerBuilder
  3. # 6
0
Votes
Undo

Using shared PBD files like you describe is a common way to work. The only downside that the IDE debugger can't enter any objects in a PBD.

A best practice is to avoid global variables. I'm not sure if your scenario would cause problems, you probably would have to try it and see what happens.

I do know that instance variables are referenced by order, not name. For example object A has three instance variables of the same type that are updated by functions in that object. Object B has an instance variable that is object A, calls functions in A and then references one of the instance variables. Now if you add a new instance variable to object A and you put it before the existing variables, the positional address in object B will be off. Object B will start referencing the wrong variable.

 

Comment
Yes I know that best practice is to avoid globals but doing so entirely causes its own set of problems and code complications. We are compromising.



When we need to debug into common.pbl we change the application's library list to use it instead of common.pbd.



I did one experiment putting one of the application globals into commonapp and using it in one of the other common.pbl objects that previously had it injected, and it worked fine both in the tiny test application in commonapp and in the real app. So my inclination is to think that there is no problem.



Thanks.
  1. Dan Cooperstock
  2. Thursday, 31 October 2019 18:28 PM UTC
Roland forgive me if I'm blunt, but I'm starting to wonder if we should avoid "instance" variables :)
  1. Miguel Leeuwe
  2. Sunday, 3 November 2019 03:00 AM UTC
I think the issue is to avoid using PBDs rather that declaring variables. Compile the whole application to avoid an issues :)
  1. David Peace (Powersoft "The PowerBuilder & C# People")
  2. Monday, 18 November 2019 14:35 PM UTC
There are no comments made yet.
  • Page :
  • 1


There are no replies made for this question yet.
However, you are not allowed to reply to this question.