Thread Tools Display Modes
04/25/14, 06:49 PM   #1
LoquaciousAndroid
Join Date: Apr 2014
Posts: 1
globals, locals, and namespaces, oh my

Apologies for the terrible Wizard of Oz reference, and more apologies if this topic has already been brought up.

I'd like to start by saying that I'm amazed at what this community has accomplished in such a short amount of time. You guys have extended ESO's UI by leaps and bounds since launch, and I love using your addons!

One thing I've noticed while checking out your code is that most of the functions live in global scope. Since lua doesn't have any real namespace support (I'm not counting tables), I humbly suggest either:

- Prefixing your global functions with a "AddOnId_" tag
- Make functions and symbols that don't need to be globally accessible, local instead

The latter is probably a better idea, since accessing locals is much faster than looking something up in _G.

I am mostly bringing this up because when I see a function like initVars declared at global scope, I'm just amazed that it hasn't collided with some other addon I've installed.

Keep in mind that the scope at which something lives is ENTIRELY dictated by the keyword "local":

Code:
local function SomewhatPrivate()
    local localToFunction = 5
    actuallyGlobal = 6
end
In that case, "actuallyGlobal" is completely accessible to any addon...sometimes this is good, sometimes it isn't.

Anyway, thanks for reading. Hopefully this helps promote clean coding, and reduces potential conflicts and random bugs when players decide to use many of the wonderful addons you authors have provided!
  Reply With Quote
04/25/14, 08:39 PM   #2
mikethecoder4
AddOn Author - Click to view addons
Join Date: Apr 2014
Posts: 13
Agreed. Had to rename all my functions because of an issue my addon was having with another very popular one.

I have prefixed all my functions with an abbreviation of my addon name, and I suggest others do the same. As more addons come out, this is probably going to become more and more of an issue.
  Reply With Quote
04/25/14, 10:16 PM   #3
LilBudyWizer
AddOn Author - Click to view addons
Join Date: Apr 2014
Posts: 32
I try to use just one global, the directory name of my addon.

Lua Code:
  1. MyAddon =
  2. {
  3.     Name="MyAddon",
  4.     Info = {},
  5.     Modules = {},
  6.     Classes = {},
  7.     Settings = {},
  8.     RefTbls = {},
  9.     State = {},
  10.     SavedVars = {},
  11. }

The above is in a file by itself loaded first. Then in each file I have:

Lua Code:
  1. local addon = MyAddon

I prefer using addon as it makes reuse easier, just one line in each file actually refers to the name of the addon. There isn't really any way around that without being able to execute a file. I would much prefer to have that line in a generic name like "init.lua" that's executed in each module so there is no reference to the actual addon name except in global.lua which defines it. If I need to use the actual addon name in the code, such as for error messages, it's addon.Name.

Within files using a module I then have:

Lua Code:
  1. local util=addon.Modules.Utility

And in the module itself:

Lua Code:
  1. local util=addon.Modules.Utility = {}

Ok, not really. The modules have to be there so it's clearer to me to actually place the creation of the table in global.lua. My settings are actually a class so Settings is an insance of that class with the actual settings in the saved variables. I found with saved variables I can't actually create them until the addon is loaded so I can't stick it in the global.lua. So each module needs an init called during the addon loaded event to set the saved variables. I don't actually refer to the saved variables in the global except through the following:

Lua Code:
  1. local SV = addon.SavedVars

Mostly just for shorthand purposes. Overall, personally, there's a big advantage to being able to access functions through a table. One of my testing functions tracks coverage, i.e. which functions have been called. With all the functions in tables I can easily list all the functions defined and never called.
  Reply With Quote
04/26/14, 01:56 PM   #4
Vuelhering
AddOn Author - Click to view addons
Join Date: Mar 2014
Posts: 169
Good idea. I should consider separating it like that, as code reuse is a big deal.
  Reply With Quote
04/26/14, 04:14 PM   #5
Kith
AddOn Author - Click to view addons
Join Date: Apr 2014
Posts: 49
The method LilBudyWizer is using is how I do my AddOns as well. That with the ability to CreateControls using the API without a name (leave name as nil) means, until I get into settings menus and the like that require names, my global 'pollution' is reduced to two entries unless I implicitly want an outside reference.

Until the bug is fixed with LUA created controls not have support for OnUpdate, i've been making my addons with the following:
Code:
-- My AddOn.xml file - loaded first
<GuiXml>
	<Controls>
		<TopLevelControl name="MyAddOn" />
	</Controls>
</GuiXml>
That control (table!) created in the xml is what I use as the root of my addon for everything else. So using the same method described above to embed functions/vars into that table but it also still has the option to just outright set MyAddOn:SetHandler('OnUpdate', Foobar) if needed.
  Reply With Quote
04/26/14, 06:27 PM   #6
skyraker
AddOn Author - Click to view addons
Join Date: Mar 2014
Posts: 154
The only issue with using a local like that is if you have more than one file accessing information in another (other than saved variables). Now, of course, removing anything that needs to be accessed outside a saved var may be a nice way to move on from that, but sometimes that presents more problems.

What most authors have moved to doing is ensuring that their main 'global' is having most of everything else be part of that initial table. So, in my instance, all my functions are members of the global table for my addon. The recommendation has been to not make a global namespace that may accidentally be used by someone else. So, my old MS.xxxxxxx members are now MyStatWin.xxxxxxx
  Reply With Quote
04/26/14, 06:57 PM   #7
Xrystal
caritas omnia vincit
 
Xrystal's Avatar
Premium Member
AddOn Author - Click to view addons
Join Date: Feb 2014
Posts: 369
Similarly, all my XML frames are prefixed with XrysGatherer and any functions/variables that are needed in other files are available in my globals file as a part of my global XRGA table.
  Reply With Quote
04/27/14, 11:45 PM   #8
LilBudyWizer
AddOn Author - Click to view addons
Join Date: Apr 2014
Posts: 32
I stuck an addon out there to make it relatively easy to see what globals your addon is creating. I called it Environmental Protection Addon (EPA). I caught where I created a global by accident. It caused the program to crash since it wasn't where it was suppose to be, but it made me think about how easy it is to accidently create global and wonder if I had done that somewhere didn't cause a crash. The program is extremely simple. It has like 20 lines of code. I thought I might as well throw it out there though. Lord knows I see a lot of variables in global that ought not be there. Surely no one else will use "name" as a variable name.
  Reply With Quote
04/28/14, 08:24 AM   #9
Myrroddin
AddOn Author - Click to view addons
Join Date: Feb 2014
Posts: 28
Is there no vararg? Warcraft added it around Burning Crusade or so, and Rift has had it since day one.

Code:
-- returns string, table
-- if put at the top of each .lua file in an AddOn, then the table is not only local, it is accessible to any Lua file in the AddOn
local AddOn, AddOnTable = ... -- the ... is a vararg
function AddOn:SomeFunction()
    AddOnTable[some_data] = someData
    table.insert(AddOnTable, someOtherData)
end
**EDIT Sorry for the broken up code blocks. The site is broken, apparently

Last edited by Dolby : 04/28/14 at 09:57 AM. Reason: fixed bbcode mess
  Reply With Quote
04/28/14, 09:26 AM   #10
ins
AddOn Author - Click to view addons
Join Date: Mar 2014
Posts: 76
To access content from one .lua file from another inside the same addon, there needs to be some globals AFAIK.

It sucks, but as mentioned elsewhere. Just put them under the same "xxxxxx." tree and it should at least be easier to find it, and separate it from anything else.
  Reply With Quote
04/28/14, 01:46 PM   #11
Xrystal
caritas omnia vincit
 
Xrystal's Avatar
Premium Member
AddOn Author - Click to view addons
Join Date: Feb 2014
Posts: 369
That was one of my first questions. But alas there apparently isn't. Wow came into using it quite late so hopefully eso will add it sooner. But as had been mentioned I just use an addon related name as a global table for the addon.


Originally Posted by Myrroddin View Post
Is there no vararg? Warcraft added it around Burning Crusade or so, and Rift has had it since day one.

Code:
-- returns string, table
-- if put at the top of each .lua file in an AddOn, then the table is not only local, it is accessible to any Lua file in the AddOn
local AddOn, AddOnTable = ... -- the ... is a vararg
function AddOn:SomeFunction()
    AddOnTable[some_data] = someData
    table.insert(AddOnTable, someOtherData)
end
**EDIT Sorry for the broken up code blocks. The site is broken, apparently
  Reply With Quote
04/28/14, 02:15 PM   #12
SinusPi
AddOn Author - Click to view addons
Join Date: Feb 2014
Posts: 18
Even better, if you just use a LOCAL table for the addon object,

Code:
  local MyAddon = {}

  function MyAddon:DoCrap()
  function MyAddon:DoMoreCrap()
... then you can choose to "show" it...

Code:
  _G.MyAddon = MyAddon
... or not.

Of course that only works if your addon is contained in one file.

But if you're REALLY paranoid about not leaving it visible (and don't care about it being debuggable ingame), then you can simply hide it again at the end of the last file to load:

Code:
  _G.MyAddon = nil
... and it's all clean again!
  Reply With Quote
04/28/14, 02:59 PM   #13
Seerah
Fishing Trainer
 
Seerah's Avatar
WoWInterface Super Mod
AddOn Author - Click to view addons
Join Date: Feb 2014
Posts: 648
Gonna link this here, too: http://www.wowinterface.com/download...OTANADDON.html
  Reply With Quote

ESOUI » Developer Discussions » General Authoring Discussion » globals, locals, and namespaces, oh my

Thread Tools
Display Modes

Posting Rules
You may not post new threads
You may not post replies
You may not post attachments
You may not edit your posts

vB code is On
Smilies are On
[IMG] code is On
HTML code is Off