Sign in to follow this  
Followers 0

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

14 posts in this topic

#1 ·  Posted (edited)

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

Share this post


Link to post
Share on other sites



#2 ·  Posted (edited)

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

Share this post


Link to post
Share on other sites

#3 ·  Posted

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?

Share this post


Link to post
Share on other sites

#4 ·  Posted

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

2 people like this

Any of my own code posted anywhere on the forum is available for use by others without any restriction of any kind._______My UDFs:

ChooseFileFolder ---- Single and multiple selections from specified path treeview listing
Date_Time_Convert - Easily convert date/time formats, including the language used
ExtMsgBox ------------- A highly customisable replacement for MsgBox
GUIExtender ----------- Extend and retract multiple sections within a GUI
GUIFrame -------------- Subdivide GUIs into many adjustable frames
GUIListViewEx -------- Insert, delete, move, drag, sort and edit ListView items
GUITreeViewEx ------ Check/clear parent and child checkboxes in a TreeView
Marquee ---------------- Scrolling tickertape GUIs
NoFocusLines --------- Remove the dotted focus lines from buttons, sliders, radios and checkboxes
Notify -------------------- Small notifications on the edge of the display
Scrollbars -------------- Automatically sized scrollbars with a single command
StringSize -------------- Automatically size controls to fit text
Toast -------------------- Small GUIs which pop out of the notification area

Share this post


Link to post
Share on other sites

#5 ·  Posted

Thanks Melba23, that sounds very reasonable!

Share this post


Link to post
Share on other sites

#6 ·  Posted

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


Forum Rules         Procedure for posting code

Share this post


Link to post
Share on other sites

#7 ·  Posted (edited)

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

Share this post


Link to post
Share on other sites

#8 ·  Posted (edited)

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

Share this post


Link to post
Share on other sites

#9 ·  Posted

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.

UDF List:

 

_AdapterConnections()_AlwaysRun()_AppMon()_AppMonEx()_BinaryBin()_CheckMsgBox()_CmdLineRaw()_ContextMenu()_ConvertLHWebColor()/_ConvertSHWebColor()_DesktopDimensions()_DisplayPassword()_DotNet_Load()/_DotNet_Unload()_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()CodingDirToHTML5FileInstallrFileReadLastChars()GeoIP databaseGUI - Only Close ButtonGUI ExamplesGUICtrlDeleteImage()GUICtrlGetBkColor()GUICtrlGetStyle()GUIEventsGUIGetBkColor()Int_Parse() & Int_TryParse()IsISBN()LockFile()Mapping CtrlIDsParseHeadersToSciTE()PasswordValidPasteBinPosts Per DayPreExpandQueue()Resource UpdateResourcesExSciTE JumpSettings INISHELLHOOKShunting-YardSignature CreatorStack()Stopwatch()StringAddLF()/StringStripLF()StringEOLToCRLF()VSCROLLWM_COPYDATAMore Examples...

 

 

Updated: 02/04/2015

Share this post


Link to post
Share on other sites

#10 ·  Posted (edited)

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

Share this post


Link to post
Share on other sites

#11 ·  Posted

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.

2 people like this

This wonderful site allows debugging and testing regular expressions (many flavors available). An absolute must have in your bookmarks.
Another excellent RegExp tutorial. Don't forget downloading your copy of up-to-date pcretest.exe and pcregrep.exe here
RegExp tutorial: enough to get started
PCRE v8.33 regexp documentation latest available release and currently implemented in AutoIt beta.

SQLitespeed is another feature-rich premier SQLite manager (includes import/export). Well worth a try.
SQLite Expert (freeware Personal Edition or payware Pro version) is a very useful SQLite database manager.
An excellent eBook covering almost every aspect of SQLite3: a must-read for anyone doing serious work.
SQL tutorial (covers "generic" SQL, but most of it applies to SQLite as well)
A work-in-progress SQLite3 tutorial. Don't miss other LxyzTHW pages!
SQLite official website with full documentation (may be newer than the SQLite library that comes standard with AutoIt)

Share this post


Link to post
Share on other sites

#12 ·  Posted

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:

Share this post


Link to post
Share on other sites

#13 ·  Posted

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


Forum Rules         Procedure for posting code

Share this post


Link to post
Share on other sites

#14 ·  Posted

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.

Share this post


Link to post
Share on other sites

Create an account or sign in to comment

You need to be a member in order to leave a comment

Create an account

Sign up for a new account in our community. It's easy!


Register a new account

Sign in

Already have an account? Sign in here.


Sign In Now
Sign in to follow this  
Followers 0