Use Structure instead of Global to declare varibles

Just starting out? Need help? Post your questions and find answers here.
Allen
Enthusiast
Enthusiast
Posts: 103
Joined: Wed Nov 10, 2021 2:05 am

Use Structure instead of Global to declare varibles

Post by Allen »

Hi,

I've read somewhere in this forum (forget where), it is a better practice to reduce the quantity of global varibles. We should use structure to group the varibles. Please see below code as an example.

Code: Select all

EnableExplicit

Global.i Int1,Int2
Global.b Flag1,Flag2
Global.s Str1,Str2

; Instead of use Global varibles as above, use structure to group the varibles together
Structure GlobalVaribles
  Int1.i
  Int2.i
  Flag1.b
  Flag2.b
  Str1.s
  Str2.s
EndStructure

Procedure P1(*P1Var.GlobalVaribles)
  *P1Var\Int1=10
  *P1Var\Flag1=#True
  *P1Var\Str1="Str1"
EndProcedure

Procedure P2(*P2Var.GlobalVaribles)
  *P2Var\Int2=20
  *P2Var\Flag2=#False
  *P2Var\Str2="Str2"
EndProcedure

Procedure Main()
  Protected GVar.GlobalVaribles
  P1(@GVar)
  Debug GVar\Int1
  Debug GVar\Flag1
  Debug GVar\Str1
  P2(@GVar)
  Debug GVar\Int2
  Debug GVar\Flag2
  Debug GVar\Str2
EndProcedure
It is a little more to type but seems less prone to mistakes. What is your opinion?

Thanks.

Allen
BarryG
Addict
Addict
Posts: 4136
Joined: Thu Apr 18, 2019 8:17 am

Re: Use Structure instead of Global to declare varibles

Post by BarryG »

Allen wrote: Sun Jul 10, 2022 5:18 amI've read somewhere in this forum (forget where), it is a better practice to reduce the quantity of global varibles
That's not true. There's no disadvantages to having many global variables.
User avatar
mk-soft
Always Here
Always Here
Posts: 6209
Joined: Fri May 12, 2006 6:51 pm
Location: Germany

Re: Use Structure instead of Global to declare varibles

Post by mk-soft »

It is no problem to have global variables, but it is clearer to combine them with structures.
Also, it is better to save this global group of variables, duplicate them, pass them as parameters.

To reduce rewriting, there are 'With' and 'EndWith'.


P.S.
Small gimmick to save program data ...

Code: Select all

EnableExplicit

; Change names
#CompanyName = "mk-soft"
#ApplicationName = "MyApp"

Global.i Int1,Int2
Global.b Flag1,Flag2
Global.s Str1,Str2

; Instead of use Global varibles as above, use structure to group the varibles together
Structure GlobalVaribles
  Int1.i
  Int2.i
  Flag1.b
  Flag2.b
  Str1.s
  Str2.s
EndStructure

; ****

Structure udtProgramData
  ; Header
  DataPath.s
  LastPath.s
  ; Data
  Save.i
  GlobalVars.GlobalVaribles
EndStructure

Global ProgramData.udtProgramData

Procedure LoadProgramData(FileName.s = "ProgramData.xml")
  Protected basepath.s, subpath.s, datapath.s, filepath.s, xml
  
  CompilerIf #PB_Compiler_OS = #PB_OS_Linux
    basepath = GetHomeDirectory()
    subpath = basepath + "." + #CompanyName + #PS$
  CompilerElse
    basepath = GetUserDirectory(#PB_Directory_ProgramData)
    subpath = basepath + #CompanyName + #PS$
  CompilerEndIf
  datapath = subpath  + #ApplicationName + #PS$
  filepath = datapath + FileName
  If FileSize(filepath) > 0
    xml = LoadXML(#PB_Any, filepath)
    If xml And XMLStatus(xml) = #PB_XML_Success
      ExtractXMLStructure(MainXMLNode(xml), @ProgramData, udtProgramData, #PB_XML_NoCase)
      FreeXML(xml)
      ProgramData\DataPath = datapath
      ProcedureReturn #True
    EndIf
  EndIf
  ProgramData\DataPath = ""
  ProcedureReturn #False
EndProcedure

; ----

Procedure SaveProgramData(FileName.s = "ProgramData.xml")
  Protected basepath.s, subpath.s, datapath.s, filepath.s, xml
  
  CompilerIf #PB_Compiler_OS = #PB_OS_Linux
    basepath = GetHomeDirectory()
    subpath = basepath + "." + #CompanyName + #PS$
  CompilerElse
    basepath = GetUserDirectory(#PB_Directory_ProgramData)
    subpath = basepath + #CompanyName + #PS$
  CompilerEndIf
  datapath = subpath  + #ApplicationName + #PS$
  If FileSize(datapath) <> -2
    If FileSize(subpath) <> -2
      CreateDirectory(subpath)
    EndIf
    If FileSize(datapath) <> -2
      CreateDirectory(datapath)
    EndIf
  EndIf
  filepath = datapath + FileName
  xml = CreateXML(#PB_Any)
  If xml
    If InsertXMLStructure(RootXMLNode(xml), @ProgramData, udtProgramData)
      FormatXML(xml, #PB_XML_ReFormat)
      SaveXML(xml, filepath)
    EndIf
    FreeXML(xml)
  EndIf
EndProcedure

; ----

Procedure P1(*P1Var.GlobalVaribles)
  With *P1Var
    \Int1+10
    \Flag1=#True
    \Str1="Str"+Str(\Int1)
  EndWith
EndProcedure

Procedure P2(*P2Var.GlobalVaribles)
  *P2Var\Int2=20
  *P2Var\Flag2=#False
  *P2Var\Str2="Str2"
EndProcedure

Procedure Main()
  Protected GVar.GlobalVaribles
  
  If LoadProgramData()
    CopyStructure(ProgramData\GlobalVars, GVar, GlobalVaribles)
    Debug "SaveCount: " + ProgramData\Save
  EndIf
  
  Debug "DataPath: " + ProgramData\DataPath
  
  P1(@GVar)
  Debug GVar\Int1
  Debug GVar\Flag1
  Debug GVar\Str1
  P2(@GVar)
  Debug GVar\Int2
  Debug GVar\Flag2
  Debug GVar\Str2
  
  CopyStructure(GVar, ProgramData\GlobalVars, GlobalVaribles)
  ProgramData\Save + 1
  SaveProgramData()
  
EndProcedure

Main()
My Projects ThreadToGUI / OOP-BaseClass / EventDesigner V3
PB v3.30 / v5.75 - OS Mac Mini OSX 10.xx - VM Window Pro / Linux Ubuntu
Downloads on my Webspace / OneDrive
Marc56us
Addict
Addict
Posts: 1600
Joined: Sat Feb 08, 2014 3:26 pm

Re: Use Structure instead of Global to declare varibles

Post by Marc56us »

When we say that we have to reduce the amount of global variable, it is a generalization for all programming languages: the goal is to reduce the amount of RAM.

Most beginners will tend to put global everywhere even if a variable is only used once. Think of the users who often have much less ram than the developers.

What is recommended is to use procedures and variables of type Protected as much as possible. This way the RAM is freed as soon as the procedure has finished the job.

It is also advisable to use FreeMemory as soon as possible, as well as FinishDatabase, CloseFile etc. to release some ram (resource handles also take some)

:wink:
infratec
Always Here
Always Here
Posts: 7588
Joined: Sun Sep 07, 2008 12:45 pm
Location: Germany

Re: Use Structure instead of Global to declare varibles

Post by infratec »

Global variables are like don't using EnableExplicit

The reasons for using EnableExplicit are the reasons to avoid global variables.
BarryG
Addict
Addict
Posts: 4136
Joined: Thu Apr 18, 2019 8:17 am

Re: Use Structure instead of Global to declare varibles

Post by BarryG »

Marc56us wrote: Sun Jul 10, 2022 9:26 amMost beginners will tend to put global everywhere even if a variable is only used once
Of course that is not a good idea. I'm referring to true global variables, such as appfolder$ and things like that; that get used all the time throughout your source, and (usually) never change. Nothing wrong with those.
Allen
Enthusiast
Enthusiast
Posts: 103
Joined: Wed Nov 10, 2021 2:05 am

Re: Use Structure instead of Global to declare varibles

Post by Allen »

mk-soft,

Thanks for the example! will study and learn from it.

Allen
Olli
Addict
Addict
Posts: 1202
Joined: Wed May 27, 2020 12:26 pm

Re: Use Structure instead of Global to declare varibles

Post by Olli »

@mk-soft

thank you for the beautiful example.
User avatar
mk-soft
Always Here
Always Here
Posts: 6209
Joined: Fri May 12, 2006 6:51 pm
Location: Germany

Re: Use Structure instead of Global to declare varibles

Post by mk-soft »

Complete code find here ...

Link: Save and Restore Program Data with Window Position
My Projects ThreadToGUI / OOP-BaseClass / EventDesigner V3
PB v3.30 / v5.75 - OS Mac Mini OSX 10.xx - VM Window Pro / Linux Ubuntu
Downloads on my Webspace / OneDrive
Allen
Enthusiast
Enthusiast
Posts: 103
Joined: Wed Nov 10, 2021 2:05 am

Re: Use Structure instead of Global to declare varibles

Post by Allen »

Thank you everyone for your opinon. Assign different functions to different procedures, use different structures to group varibles of different function together will definitely improve my technique to maintain/debug my programs.

Allen
Post Reply