Jump to content

This site uses cookies. By continuing to browse the site you are agreeing to our use of cookies. Find out more here. X
X


Photo

if global variables should be avoided, what's the best alternative? (in the included example)


  • Please log in to reply
13 replies to this topic

#1 Imbuter2000

Imbuter2000

    Prodigy

  • Active Members
  • PipPipPip
  • 189 posts

Posted 31 December 2012 - 05:02 PM

I've a general question about the best practice in programming with function in AutoIT or in general:

supposing to have multiple unrelated variables that you set only inside a function and read outside (after) that function, how would you do?
would you declare them as global at the very beginning of the script? or return the variables from the function as an array (losing the useful variable names)? what's the best/most used practice?
I read that global variables should be avoided... but I can't find a better alternative...

Example of how I'ld do such a script, with global variables:

Global $current_song_names, $last_query_PCname, $last_query_time some code aaaaaa... query() some code bbbbbb... query() some code cccccc... query() some code dddddd... Msgbox("","", $current_song_names & @CRLF & $last_query_PC_name & @CRLF & $last_query_time) Func query()      some code ppppp...      $current_song_names &= FileRead("c:\current_song_name.txt") & @CRLF      $last_query_PCname = @ComputerName      $last_query_time = @HOUR & ":" & @MIN & ":" & @SEC      some code qqqqq... EndFunc



How would you do it instead?

Edited by Imbuter2000, 31 December 2012 - 05:08 PM.








#2 Quual

Quual

    Seeker

  • Active Members
  • 49 posts

Posted 31 December 2012 - 05:10 PM

here is one method

Func MsgboxQueryResults()     Local $current_song_names, $last_query_PCname, $last_query_time     some code aaaaaa...     query($current_song_names, $last_query_PCname, $last_query_time)     some code bbbbbb...     query($current_song_names, $last_query_PCname, $last_query_time)     some code cccccc...     query($current_song_names, $last_query_PCname, $last_query_time)     some code dddddd...     Msgbox("","", $current_song_names & @CRLF & $last_query_PC_name & @CRLF & $last_query_time) EndFunc Func query(ByRef $current_song_names, ByRef $last_query_PCname, ByRef $last_query_time)      some code ppppp...      $current_song_names &= FileRead("c:\current_song_name.txt") & @CRLF      $last_query_PCname = @ComputerName      $last_query_time = @HOUR & ":" & @MIN & ":" & @SEC      some code qqqqq... EndFunc

Edited by Quual, 31 December 2012 - 05:12 PM.


#3 Imbuter2000

Imbuter2000

    Prodigy

  • Active Members
  • PipPipPip
  • 189 posts

Posted 31 December 2012 - 05:28 PM

Right, byref provides an alternative...
but is it a better practice? should I always prefer it? even when the list of variables is long and/or some of them are setted and used only when specific limited conditions are met?

#4 Melba23

Melba23

    I'm old - what's your excuse?

  • Moderators
  • 21,758 posts

Posted 31 December 2012 - 06:05 PM

Imbuter2000,

I really would not worry about it too much. The nature of AutoIt makes it difficult to avoid Global variables - so if you feel the need to use them then do so. Personally I would rather have legible code with some sensible Global variables than a psuedo-elegant web of parameters passed between functions - remember you are going to have to maintain this code in the future. ;)

Just try and avoid making every variable in the script Global in scope - that is not the way to go. :D

M23
  • Xandy and Flaky like this
StringSize - Automatically size controls to fit text                                                               ExtMsgBox - A user customisable replacement for MsgBox
Toast - Small GUIs which pop out of the Systray                                                                Marquee - Scrolling tickertape GUIs
Scrollbars - Automatically sized scrollbars with a single command                                   GUIFrame - Subdivide GUIs into many adjustable frames
GUIExtender - Extend and retract multiple sections within a GUI                                      NoFocusLines - Remove the dotted focus lines from buttons, sliders, radios and checkboxes
ChooseFileFolder - Single and multiple selections from specified path tree structure      Notify - Small notifications on the edge of the display
Date_Time_Convert - Easily convert date/time formats, including the language               GUIListViewEx - Insert, delete, move, drag, sort and edit ListView items

#5 Imbuter2000

Imbuter2000

    Prodigy

  • Active Members
  • PipPipPip
  • 189 posts

Posted 31 December 2012 - 06:42 PM

Thanks Melba23, that sounds very reasonable!

#6 kylomas

kylomas

    FUBAR

  • MVPs
  • 3,098 posts

Posted 31 December 2012 - 09:01 PM

Imbuter2000,

This subject comes up every so often. If you search the forum you will find some excellet discussion/explanation of technical requiremets and coding styles.

kylomas

"Really?, How Do you know the're not random numbers?"

 

Forum Rules         Procedure for posting code

 

"A child educated only at school is an uneducated child."

    - George Santayana

 

"Never miss a good chance to shut up."

    - Will Rogers
 


#7 DicatoroftheUSA

DicatoroftheUSA

    Universalist

  • Active Members
  • PipPipPipPipPipPip
  • 556 posts

Posted 31 December 2012 - 09:33 PM

For me the problem I have with globals is when reviewing a script. I ask myself, where did that come from and what should be it be set to? With a long enough script, that can become difficult to answer. If the value is specific, or passed to the function there is no question. Of course to helps to prefix global variables, eg $gsStuff.

About the only variable I prefer to be global when it could be local is magic numbers constants. Because they can help with clarity.

for example
global const $gciStopSign=16 global const $gciYesandNo=4 MsgBox($gciStopSign+$gciYesandNo,"hugh","hello")

Edited by DicatoroftheUSA, 31 December 2012 - 09:40 PM.


#8 czardas

czardas

  • MVPs
  • 7,049 posts

Posted 01 January 2013 - 09:54 AM

Another common use for Global variables is for flags which are set to trigger events on receiving windows messages. For example to interrupt a running script when clicking on a button. There must be many instances where using globals will be at least the easiest, if not sometimes the only possible solution. I'm absolutely in agreement with all the comments above.

Edited by czardas, 01 January 2013 - 07:30 PM.


#9 guinness

guinness

    all-consuming swarm in inconspicuous disguise

  • Developers
  • 17,529 posts

Posted 01 January 2013 - 10:35 AM

About the only variable I prefer to be global when it could be local is magic numbers constants. Because they can help with clarity.

I would prefer some sort of pre-processor, but you're correct this is a good approach.

Example List: _AdapterConnections()_AlwaysRun()_AppMon()_AppMonEx()_BinaryBin()_CheckMsgBox()_CmdLineRaw()_ContextMenu()_ConvertLHWebColor()/_ConvertSHWebColor()_DesktopDimensions()_DisplayPassword()_Fibonacci()_FileCompare()_FileCompareContents()_FileNameByHandle()_FilePrefix/SRE()_FindInFile()_GetBackgroundColor()/_SetBackgroundColor()_GetConrolID()_GetCtrlClass()_GetDirectoryFormat()_GetDriveMediaType()_GetFilename()/_GetFilenameExt()_GetHardwareID()_GetIP()_GetIP_Country()_GetOSLanguage()_GetSavedSource()_GetStringSize()_GetSystemPaths()_GetURLImage()_GIFImage()_GoogleWeather()_GUICtrlCreateGroup()_GUICtrlListBox_CreateArray()_GUICtrlListView_CreateArray()_GUICtrlListView_SaveCSV()_GUICtrlListView_SaveHTML()_GUICtrlListView_SaveTxt()_GUICtrlListView_SaveXML()_GUICtrlMenu_Recent()_GUICtrlMenu_SetItemImage()_GUICtrlTreeView_CreateArray()_GUIDisable()_GUIImageList_SetIconFromHandle()_GUIRegisterMsg()_GUISetIcon()_Icon_Clear()/_Icon_Set()_IdleTime()_InetGet()_InetGetGUI()_InetGetProgress()_IPDetails()_IsFileOlder()_IsGUID()_IsHex()_IsPalindrome()_IsRegKey()_IsStringRegExp()_IsSystemDrive()_IsUPX()_IsValidType()_IsWebColor()_Language()_Log()_MicrosoftInternetConnectivity()_MSDNDataType()_PathFull/GetRelative/Split()_PathSplitEx()_PrintFromArray()_ProgressSetMarquee()_ReDim()_RockPaperScissors()/_RockPaperScissorsLizardSpock()_ScrollingCredits_SelfDelete()_SelfRename()_SelfUpdate()_SendTo()_ShellAll()_ShellFile()_ShellFolder()_SingletonHWID()_SingletonPID()_Startup()_StringCompact()_StringIsValid()_StringRegExpMetaCharacters()_StringReplaceWholeWord()_StringStripChars()_Temperature()_TrialPeriod()_UKToUSDate()/_USToUKDate()_WinAPI_Create_CTL_CODE()_WinAPI_CreateGUID()_WMIDateStringToDate()/_DateToWMIDateString()Au3 script parsingAutoIt SearchAutoIt3 PortableAutoIt3WrapperToPragmaAutoItWinGetTitle()/AutoItWinSetTitle()CodingDirToHTML5FileInstallrGeoIP databaseGUI - Only Close ButtonGUI ExamplesGUICtrlDeleteImage()GUICtrlGetBkColor()GUICtrlGetStyle()GUIEventsGUIGetBkColor()Int_Parse() & Int_TryParse()LockFile()Mapping CtrlIDsParseHeadersToSciTE()PasswordValidPasteBinPosts Per DayPreExpandQueue()Resource UpdateResourcesExSciTE JumpSettings INISHELLHOOKShunting-YardSignature CreatorStack()Stopwatch()StringAddLF()/StringStripLF()StringEOLToCRLF()VSCROLLWM_COPYDATAMore Examples...
Updated: 26/09/2014


#10 jaberwacky

jaberwacky

    RegExp("\m/")

  • Active Members
  • PipPipPipPipPipPip
  • 3,205 posts

Posted 01 January 2013 - 05:54 PM

There isn't a big problem with passing arguments to your functions. This means that you don't have to go scouring your code to find the definition of some global variable which is most likely able to change at any given moment under all sorts of conditions. This is especially pertinent for large code bases. Exceptions to this are native global constants and user defined global constants. If your argument list becomes too long then it's time to look into breaking your function into smaller functions. This helps with comprehension of the code by reducing complexity.

Edited by jaberwocky6669, 01 January 2013 - 05:55 PM.


#11 jchd

jchd

    Whatever your capacity, resistance is futile.

  • MVPs
  • 5,321 posts

Posted 01 January 2013 - 06:55 PM

Another reason to prefer parameters to globals is that functions can be reused much more easily in other projects. That helps modularity to a great extend: you don't have to practice surgery to export functions and that favors grouping famillies in reuseable includes.

But of course it isn't a strict rule to apply blindly and go away happy in all cases. For instance, writing a function taking 83 arguments is obviously a bad design in the first place.
  • czardas and jaberwacky like this

SQLite official website with full documentation (may be newer than the SQLite library that comes standard with AutoIt)

A work-in-progress SQLite3 tutorial. Don't miss other LxyzTHW pages!

SQL tutorial (covers "generic" SQL, but most of it applies to SQLite as well)

An excellent eBook covering almost every aspect of SQLite3: a must-read for anyone doing serious work.

 

SQLite Expert (freeware Personal Edition or payware Pro version) is a very useful SQLite database manager.

SQLitespeed is another feature-rich premier SQLite manager (includes import/export). Well worth a try.

 

PCRE v8.33 regexp documentation latest available release and currently implemented in AutoIt beta.

RegExp tutorial: enough to get started

Another excellent RegExp tutorial. Don't forget downloading your copy of up-to-date pcretest.exe and pcregrep.exe here

This wonderful site allows debugging and testing regular expressions (many flavors available). An absolute must have in your bookmarks.


#12 czardas

czardas

  • MVPs
  • 7,049 posts

Posted 01 January 2013 - 07:12 PM

Good points jchd. Perhaps there are one or two exceptions where large numbers of parameters are possibly acceptable. Some bitwise functions can take up to 255 parameters. I never saw anyone try it though. :wacko:

#13 kylomas

kylomas

    FUBAR

  • MVPs
  • 3,098 posts

Posted 01 January 2013 - 07:30 PM

You'll notice that a common theme is coding style. Establishing a variable naming convention is important, especially in a large project.

As far as scope is concerned, consider the following code based on your OP
; scope is local to script making variables in scope to any called fuction local $current_song_names = '123', $last_query_PCname = 'abc', $last_query_time = '2013, Happy New Year!' query() _two() Func query()      ConsoleWrite($current_song_names & @lf & $last_query_PCname & @lf & $last_query_time & @lf)     local $current_song_names = 'hmmm...something changed'  ; scope is local to function query() making the value visible only within this function     ; from the script perspective there are two variable named $current_song_names at this point, one visible at the script level and one local to this function     ConsoleWrite('variable after chaged within function = ' & $current_song_names & @LF) EndFunc func _two()     ConsoleWrite($current_song_names & @LF)  ; using the variable with script scope, the var with function scope was destroyed when the func ended EndFunc


kylomas

"Really?, How Do you know the're not random numbers?"

 

Forum Rules         Procedure for posting code

 

"A child educated only at school is an uneducated child."

    - George Santayana

 

"Never miss a good chance to shut up."

    - Will Rogers
 


#14 AZJIO

AZJIO

    Universalist

  • Active Members
  • PipPipPipPipPipPip
  • 1,596 posts

Posted 01 January 2013 - 10:37 PM

No need to fear the global variables. If a person does not understand, he rushes from one extreme to another.
Global variables is not a crime. It is important that your script gave the declared results.
When you have a complex script, you will understand how to organize. You won't be able to perceive disordered information.




0 user(s) are reading this topic

0 members, 0 guests, 0 anonymous users