Page 1 of 1

Use Structure instead of Global to declare varibles

Posted: Sun Jul 10, 2022 5:18 am
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

Re: Use Structure instead of Global to declare varibles

Posted: Sun Jul 10, 2022 6:28 am
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.

Re: Use Structure instead of Global to declare varibles

Posted: Sun Jul 10, 2022 8:49 am
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()

Re: Use Structure instead of Global to declare varibles

Posted: Sun Jul 10, 2022 9:26 am
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:

Re: Use Structure instead of Global to declare varibles

Posted: Sun Jul 10, 2022 9:32 am
by infratec
Global variables are like don't using EnableExplicit

The reasons for using EnableExplicit are the reasons to avoid global variables.

Re: Use Structure instead of Global to declare varibles

Posted: Sun Jul 10, 2022 9:40 am
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.

Re: Use Structure instead of Global to declare varibles

Posted: Sun Jul 10, 2022 9:44 am
by Allen
mk-soft,

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

Allen

Re: Use Structure instead of Global to declare varibles

Posted: Sun Jul 10, 2022 10:27 am
by Olli
@mk-soft

thank you for the beautiful example.

Re: Use Structure instead of Global to declare varibles

Posted: Sun Jul 10, 2022 10:32 am
by mk-soft
Complete code find here ...

Link: Save and Restore Program Data with Window Position

Re: Use Structure instead of Global to declare varibles

Posted: Sun Jul 10, 2022 11:24 am
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