Announcement

Collapse
No announcement yet.

Need some advice

Collapse
X
 
  • Filter
  • Time
  • Show
Clear All
new posts

  • Need some advice

    Hello,

    I need a little advice about how to handle large arrays of data
    that need to be visable in every window/dialog/child. I have heard
    and been trained on the idea that GLOBAL is bad, But what can you
    do when you have a few large arrays that need to be addressed from
    every dialog and window you have? Is this the only way out?

    Thanks for the advice!

    ------------------
    Cheers

  • #2
    Mark;

    Globals are not bad !

    They are simply discouraged.

    What this means, IMO, is that Globals shouldn't be overused.

    Globals are absolutely necessary. Even C programs use a lot of Globals.


    Here are the rules I use:

    (1) Use local variables (including static) as often as is
    reasonably possible.

    (2) If functions/subs need some specific data, pass the data as
    parameters first before resorting to Globals.

    (3) If Globals are the only (and best way) to handle some specific
    data, then specify Global variable names with a consistant prefix.
    I like to use App_ as a prefix (ie. GLOBAL App_MyArray() ). This
    prevents confusion in your code. Global variables should never
    use generic names like X&, Y&, N&() , etc.

    Once again, Globals are NOT bad. The problem is that they are often
    abused or used incorrectly. A well written program will have Globals
    but the number of Global variables used will always be kept to a
    minimum and they are used "very" carefully.



    ------------------
    Chris Boss
    Computer Workshop
    Developer of "EZGUI"
    http://cwsof.com
    http://twitter.com/EZGUIProGuy

    Comment


    • #3
      Thanks for clearing that up!

      ------------------
      Cheers

      Comment


      • #4
        Mark,

        I am an encapsulation freak.
        I usually have only one global variable in most of my programs:
        ghHeap; which is returned from HeapCreate. I then use HeapAlloc to allocate
        memory for a udt that contains all the variables that need to be shared.
        This value is used as the lParam in CreateDialogParam.
        Code:
        For Arrays I use
        TYPE MyDataInfo
          MydwArry AS DWORD PTR
          MyByteArray AS BYTE PTR 
        END TYPE 
        
        DIM MyData AS MyDataInfo PTR
        First I allocate memory for the udt:
        MyData = HeapAlloc(ghHeap,%HEAP_NO_SERIALIZE OR %HEAP_ZERO_MEMORY,LEN(MyDataInfo))
        
        Then for the array
        @MyData.MyDwArray = HeapAlloc(ghHeap,%HEAP_NO_SERIALIZE OR %HEAP_ZERO_MEMORY,(NumOfElements-1)*4))
        
        To Access ArrayData
        DataIWant = @[email protected][Index]
        James


        ------------------




        [This message has been edited by jcfuller (edited September 02, 2000).]

        Comment


        • #5
          Mark, one last thought:

          If Globals were so bad, programming language developers wouldn't
          support them in their compilers.

          VB, C++, Delphi, PowerBasic all allow Globals.

          There is a good reason for this, we need them.

          As far as James method, IMO I prefer to let the compiler
          handle creating memory space and tracking it. Thats why the
          compiler allows Globals. Likely the compiler does the "same thing"
          James code does for us. Just use Globals.

          There is absolutely NO harm in using globals in your apps if you
          the rules I mentioned above. By using a special prefix for "all"
          Globals you elimiate the most common bugs created by using Globals
          (double references). My apps use anywhere from just a few to a couple
          dozen globals depending on what is needed.




          ------------------
          Chris Boss
          Computer Workshop
          Developer of "EZGUI"
          http://cwsof.com
          http://twitter.com/EZGUIProGuy

          Comment


          • #6
            Mark,

            GLOBAL variables were a problem in the bad old days when some languages
            only had global variables but where you have the choice of GLOBAL, STATIC
            and LOCAL, you can accurately target exactly the scope you need with the
            variables you need.

            Where you need access to a variable across a complete application, giving
            a variable GLOBAL scope is the most efficient way to do it, where you only
            need a transient value, LOCAL works fine and where you need to have a
            constant that can be changed each time it is needed but remains loaded in
            memory, a STATIC variable does the job you need.

            The attempt to avoid GLOBAL variables is basically a matter of fashion but
            it can also involve a rediculous archipeligo of additional stack parameter
            which is a lot more complex and also less efficient than a GLOBAL
            variable.

            The operating system maintains lists of GLOBAL variables with things like
            handles, process IDs etc.. so much of the fashion of avoiding GLOBAL
            variables is only delegating this capacity to the operating system at the
            expense of additional overhead.

            Regards,

            [email protected]

            ------------------
            hutch at movsd dot com
            The MASM Forum

            www.masm32.com

            Comment


            • #7
              Sure the over use of globals might be bad.

              But, doing insane things instead is also bad.

              1. Maping all your globals into one large byte array
              and then saying you just have one global, one array.

              Problem: You lose the benifits of using easy to read
              variable names.

              2. Passing data from function, to function, to function. . .
              to sub.

              Problem: Overhead and confusion. You might end up passing
              large numbers of variables.

              3. Using one big type statement to hold all the globals.

              Problem: Maybe overhead problems and looks a little silly,
              just using plain globals would be better.


              Tip on naming variables:

              Place a "g_" in front of all globals as in:

              Global g_waypointX As Long
              Global g_waypointY As Long

              That way you can spot the globals very quickly and not
              get confused into thinking they are locals.

              On a large program you should use "Modules" of code.
              I have a game PB program that has a Combat module,
              a Movement module and about 15 other modules.
              Each module is a related group of subs and functions. I want to
              have module level shared variables, since PB does not support
              module level variables I make my own using globals and a naming
              convention.

              All subs/functions from the combat module will use Globals
              that begin with the letters "m1_"

              All subs/functions from the combat module will use Globals
              that begin with the letters "m2_"

              I only will use m1_ or m2_ globals in their modules and no
              place else, ever!

              I have 920 different globals and no confusing at all as to
              what each does. The program runs like a clock. The code is
              easy to read and understand.

              The Global is the variable sharing tool that PowerBasic gives
              you to work with, use it when it is needed. Just be careful
              not to confuse globals for locales and be very careful with
              how they are used. Don't allow one part of the program to zap
              a global that causes failure in another part of the program.
              Those can be very hard to find problems.

              VB allows you to have classes and modules level variables,
              those are a step away from globals at a cost of speed.

              The new language C# from Microsoft does not even have globals.
              All varibles are properies of a class or namespace class, very
              new way of doing things.

              Tim


              ------------------

              Comment


              • #8

                Some of the reasons I opt for minimal globals are due to my programming style.

                1.Encapsulation
                I elect not to use a rambling SELECT CASE for my dialog message procedures.
                I have separate functions for each message.
                How to share data between these functions?
                Well GLOBALS are fine if I have only one dialog in my program but what happens when I have
                five, ten or more dialogs in a program. The number of globals increase rapidly.
                Many of these dialogs may have similar or identical data so I start inventing new names so as to
                not have conflicts. As I add more dilaogs to the project the process gets crazy.
                Now If I use a UDT for the data the only name change is in the UDT name and the member
                names can remain the same.

                2.Prototying.
                Very often I will prototype a set of functions in their own exe before adding them to a project.
                By using a UDT for shared data I can then just INCLUDE the code without worrying about
                conflicting variable names.

                3.Memory Usage.
                Say I have a set of similar mathmatical routines that can use either double, single, or integer data
                depending on user slection. There are 50 separate variables. Now if I use globals I have to have
                150 different variables with 150 different names. If I use 3 different UDT's, and allocate the memory
                for it myself , I only need memory for 50 variables. Also all the member names of each UDT can be
                the same.


                James


                ------------------

                Comment


                • #9
                  James, your use of "module" level UDT's sounds great.

                  Yes, Global UDT's are great for Encapsulation.

                  Great for "members" of an "object" and very easy to store to the
                  hard drive.

                  My super large PB Game program that has the 920 Globals in it,
                  about 90 of those Globals are UDT's that range in size from
                  12 bytes to 840 bytes.

                  It would be foolish to take all 920 Global Longs, Strings,
                  Arrays and UDT's and make them part of one super UDT just for
                  the sake of having one and only one Global to live up to the
                  silly rule that globals are bad.
                  (Plus the compiler would not like it)

                  If you use a giant UDT or many globals you are still using
                  the same memory, you are just accessing it differently.
                  As long as it works and the code is easy to read and does
                  not lead to errors, then it sounds like a good method to me.

                  One trick I love to use to pass variables to a DLL is to
                  make a UDT of pointers to globals the DLL needs and pass the
                  UDT to the DLL. The DLL can then use the UDT pointers to
                  reach back to the globals in the main program.


                  Tim



                  ------------------

                  Comment


                  • #10
                    Originally posted by Tim Wisseman:
                    James, your use of "module" level UDT's sounds great.

                    If you use a giant UDT or many globals you are still using
                    the same memory, you are just accessing it differently.
                    As long as it works and the code is easy to read and does
                    not lead to errors, then it sounds like a good method to me.

                    Tim,
                    Your right if you only have one UDT.
                    In the senerio I presented in #3 you don't allocate the memory
                    for the UDT until after the selection of the data type.

                    James

                    ------------------


                    [This message has been edited by jcfuller (edited September 03, 2000).]

                    Comment


                    • #11
                      James,

                      What do you gain from the added complexity?

                      ------------------

                      Comment


                      • #12
                        Tim,
                        Modularity in my Dialog based projects. If you've tried my
                        PBWinADP you will see this concept in action.

                        James


                        ------------------

                        Comment


                        • #13
                          Tim,

                          I think its a matter of the preferred architecture that shapes the type of
                          code that is written. I have seen some of James's code design which I
                          consider to be very sophisticated architecture but it is necessarily a more
                          complex code design.

                          I come from a background of SDK C and have written much that style of code
                          in both 16 and 32 bit windows since I started as it is more closely related
                          to the operating system design and the hardware.

                          I personally have no problems with C style switch block / Basic Select Case
                          asm block .if message processing because I like the sheer code size
                          efficiency of that design.

                          I have played with other architectures in asm, message despatchers, message
                          crackers etc ... but in my own case, I cannot improve on the fundamental
                          operating system architecture, a message processing function addressed in the
                          WNDCLASSEX and a normal message loop in the WinMain that despatches messages
                          to it.

                          I have a reasonable grasp of what James is after and it seems to be a method
                          of isolating complete modules so they can be used as code blocks, objects if
                          you like, and pick up the efficiency of block code reuse.

                          I am of the more traditional approach where I isolate a function and other
                          dependent functions and use tham as reusable code blocks in a seperate file.

                          If a later version of PowerBASIC has the capacity to build static libraries,
                          bothe the architecture that James uses and the traditional architecture will
                          become a lot more powerful in terms of code reuse.

                          Fortunately at the moment, the low level capacity of the PowerBASIC compiler
                          allows different architecture to be designed which is part of the advantage
                          of having this capacity.

                          Regards,

                          [email protected]

                          ------------------
                          hutch at movsd dot com
                          The MASM Forum

                          www.masm32.com

                          Comment


                          • #14
                            It most likely better that programmers master the more
                            traditional approach of using global memory before moving
                            on to the more complex methods. The simple traditional approach
                            of using global memory and reusable code blocks in
                            seperate files, is still a very powerful way of doing things.

                            Does anyone here think that Mark, who is learning about globals
                            should start off using Jame's method instead of traditional
                            global memory?

                            Tim


                            ------------------

                            Comment


                            • #15
                              IMO, it is better to use the features built into the programming
                              language before using other techniques. Using Globals in a PB app
                              are so easy, why waste time messing with complex memory routines.

                              Now, it is true that in some instances you "must" use such
                              techniques. One example is in writing a "custom control DLL".
                              The Window procedures for custom controls "must" access memory
                              using Windows Global memory handles, so each window will have
                              a unique memory block. I am currently working on a
                              "Custom Control Development kit" (first for in house and maybe
                              later for sale) and I have to access memory like James does.

                              Yet, most PB apps "don't" need such memory access techniques.
                              The reason programmers use Basic is the ease of use of the
                              language. Seeing the PB compiler offers Globals, it only makes
                              sense to use them. There are NO dangers or problems in using
                              PB Globals, if you follow good programming practices. I have
                              seen quite a bit of code posted on the forum, where Globals
                              don't use a consistant Prefix in front of the Global variable
                              names. If the few rules I mentioned above are following, there
                              shouldn't be any problem in using Globals.

                              One of the first rules of programming, I follow is :

                              Use the features of the programming language first, before
                              resorting to any lower level code. The old adage of
                              "Keep it Simple" applies here.


                              ------------------
                              Chris Boss
                              Computer Workshop
                              Developer of "EZGUI"
                              http://cwsof.com
                              http://twitter.com/EZGUIProGuy

                              Comment


                              • #16
                                One of the downside of globals is that their use makes multi-threaded
                                /thread safe programming much more difficult since global data needs to
                                be protected against possible corruption/ovewrites from the threads
                                accessing the global - it's easier to do multi-threaded programming when using
                                stack variables/dynamic memory.

                                Although not all the programs I write are multi-threaded I design
                                most of my apps so that they are thread-safe.

                                Careful use of globals in single-threaded programs is okay although
                                I tend to rely on stack variables. It makes it much easier to
                                see at a glance what data variables are accessible to each function/sub.

                                YMMV

                                Cheers

                                Florent

                                ------------------

                                Comment

                                Working...
                                X