Thread Tools Display Modes
11-28-05, 03:26 PM   #1
Rowne
A Fallenroot Satyr
 
Rowne's Avatar
AddOn Author - Click to view addons
Join Date: Sep 2005
Posts: 26
OO initiative.

Allow me to get two things out of the way; 1) this has nothing to do with Ace, 2) I'm not trying to stir up trouble.

I've been wondering lately with the advent of object-oriented programming as described in [Programming in Lua], why more authors haven't switched to object-oriented code, I gather it's mostly because of the lack of awareness of it (at a guess). Blizzard uses non-OO code themselves, which I would surmise that most people use as a base to create their own AddOns from.

The reason I promote OO is because unlike the usual script based system of coding, OO doesn't leave names lying around in the global namespace. Here's an example ...

Code:
function MyAddOn_SomeFunc()
   Some_Var = value
end

function MyAddOn_SomeOtherFunc()
   Another_Var = value
end

function MyAddOn_AnotherFunc()
   Yet_Another_Var = value
end
In the global namespace you'd then have ...

MyAddOn_SomeFunc
MyAddOn_SomeOtherFunc
MyAddOn_AnotherFunc
Some_Var
Another_Var
Yet_Another_Var

Now here's the OO approach ...

Code:
MyAddOn = {
   someVar = value,
   anotherVar = value,
   yetAnotherVar = value
}

function MyAddOn:SomeFunc()
   self.someVar = value
end

function MyAddOn:SomeOtherFunc()
   self.anotherVar = value
end

function MyAddOn:AnotherFunc()
   self.yetAnotherVar = value
end
This would leave only MyAddOn in the global namespace and nothing more. In fact, if you put your constants in a MyAddOn.Const table and your main AddOn in a MyAddOn.Obj table (take a look at ZooKeeper on wowace.com to see what I mean -- I'll get those uploaded here soon) then you only have MyAddOn in the global namespace, period.

In fact, a while back, Eraphine was designing an AddOn and he had a var with something like ElapsedTime in it. His AddOn wasn't working. I told him that it was because it was a constant, it was no doubt being snatched up by another AddOn which was also using it as a constant inthe namespace and nil'd. He was, of course, a bit doubting of this; "Nah, that can't be right." He tried it though and lo and behold, that's what it was.

On changing the variable to self.ElapsedTime, everything worked dandy.

This is why I'm hoping I can get more authors to switch to OO -- because it's less pollution within the name-space, it's better all in all and it'll mean less collision between AddOns. Now some people have took it that I'm an elitist in regards to Ace, that's not true. It's simply a misunderstanding based on an assumption. I've said that Ace is a really good system and that I'm not so sure about non-Ace AddOns.

Why is this?

It's because most non-Ace AddOns still use flat-function/flat-variable system, those are prone to, as I said, polluting the namespace and collision. It's nothing to do with that I think 'Ace is the better dependency'. That's just been assumed. It's to do with the fact that in the Ace community, we're all using OO. You don't have to use Ace to use OO. So allow me to stress that right now.

I tried really, really hard to present this without being obnoxious, I honestly did. If I came off wrong, feel free to yell at me because I probably deserve it but I'm just trying to convey a view here. I don't mean any harm by it. Really.

The reason I'll often look at a non-Ace(D) AddOn and then decide not to use it is because it isn't OO. If it was OO or at the very least, tabled then I'd snap it up and give it a look. I think the problem with flooding the global namespace (like Blizzard admittedly does) is something of a problem that coders might want to look into.

Don't take this as a "You should work this way!", it isn't. It's just a "Hey, here's a different possibility, check it out and see if you like it?"

So ... yanno, my thoughts, take 'em or leave 'em but I thought I'd share.
__________________
There can only be so many ways of doing things; rope rubs against rope and it causes fire, fire cleanses all. Sadly, the ropes can't be around to appreciate it.

Short: Tolerance FTW?
  Reply With Quote
11-28-05, 03:40 PM   #2
Cairenn
Credendo Vides
 
Cairenn's Avatar
Premium Member
WoWInterface Admin
Join Date: Mar 2004
Posts: 7,134
Sharing in a non-inflammatory manner is a good thing. That's why these forums are here and why the #wowi-lounge irc channel exists. Neutral territory for coders following various schools to come together to *discuss* ways in which to accomplish things. Thanks for posting this Rowne.
__________________
“Do what you feel in your heart to be right — for you’ll be criticized anyway.” ~ Eleanor Roosevelt
~~~~~~~~~~~~~~~~~~~
Co-Founder & Admin: MMOUI
FaceBook Profile, Page, Group
Avatar Image by RaffaeleMarinetti

Last edited by Cairenn : 11-28-05 at 04:00 PM.
  Reply With Quote
11-28-05, 04:03 PM   #3
Beladona
A Molten Giant
 
Beladona's Avatar
AddOn Author - Click to view addons
Join Date: Mar 2005
Posts: 539
good post Rowne. I tried to bring this up months ago, but it kind of died out. This is exactly how I code. Minimizes the "surface" space of your addon in the main namespace, making coding a lot easier to read, use, and also makes your variables less likely to overlap one someone else made...
  Reply With Quote
11-28-05, 04:16 PM   #4
AnduinLothar
Nobody of Importance
 
AnduinLothar's Avatar
AddOn Author - Click to view addons
Join Date: Oct 2005
Posts: 95
We've been doing OO in a similar way in Cosmos libraries since beta. Example:
Code:
MyAddOn = {};

MyAddOn.SomeFunc = function()
   
end

MyAddOn.SomeOtherFunc = function()

end

MyAddOn.AnotherFunc = function()

end
The only real difference is that it doesn't pass the MyAddOn table as the first argument and that you call it using '.' and not ':' Ex: MyAddOn.AnotherFunc()

In some cases having the self passed may be useful, say for abstracting frame code, but for most code I've seen it's not used. What are some isntances in which it might be good to have?

Also I'd have to say the method of OO that you listed confused the heck out of me when I first read similar code, but I think the example I gave is a little easier to understand at first glance. It's less complex.
  Reply With Quote
11-28-05, 04:36 PM   #5
sacha
An Aku'mai Servant
 
sacha's Avatar
AddOn Author - Click to view addons
Join Date: Jun 2005
Posts: 38
Great thread - Im learning something today
BTW - Is there any advantage/disadvantage to using an approach as below?

Code:
local function somePrivateFunction()

end

local function somePrivateFunction2()

end

MyAddon = {

  somePublicVariable = value,
  somePublicVariable2 = value

};

MyAddon.somePublicFunction = function()
  -- may use a local function in here, or not
end


MyAddon.somePublicFunction2 = function()
  -- may use a local function in here, or not
end
Also I am not sure whats the significance of using "function MyAddOn:AnotherFunc()" as opposed to "MyAddon.somePublicFunction2 = function()" , I will read the lua docs again, but if anyone can explain it to me in simple terms Id appreciate it
  Reply With Quote
11-28-05, 04:41 PM   #6
tardmrr
Lua Ninja
AddOn Author - Click to view addons
Join Date: Jun 2005
Posts: 133
The colon versus the dot notation is what they like to call "syantactic sugar." It's short hand for passing the table as the first argument.

All these are the same:
Code:
function Table.func(self,...)

end

Table.func(Table,...)
Table:func(...)

function Table:func(...)

end

Table.func(Table,...)
Table:func(...)
  Reply With Quote
11-28-05, 04:57 PM   #7
AnduinLothar
Nobody of Importance
 
AnduinLothar's Avatar
AddOn Author - Click to view addons
Join Date: Oct 2005
Posts: 95
Also note that using MyAddOn.SomeFunc = function() allows you to replace a function that's already been defined whereas I believe function SomeFunc() will throw an error if SomeFunc already exists. Also I think function MyAddOn.SomeFunc() throws an indexing error anyway.
  Reply With Quote
11-28-05, 05:10 PM   #8
Rowne
A Fallenroot Satyr
 
Rowne's Avatar
AddOn Author - Click to view addons
Join Date: Sep 2005
Posts: 26
Anduin I didn't simplify it because I didn't want to patronize or underestimate the intelligence of my fellow coder. So I went straight for the advanced examples, knowing that you and everyone else would figure it out. Sorry.

Colons versus periods I agree with what Tardmrr has said, it's basically just a different way of processing variables. I use it very often in Ace for either cross-modularity between Lua files (as evidenced in Visor) or even between different AddOns, when it's needed. By being able to chuck 'self' around with gay abandon, it makes things like that a doddle. I think that's the only difference though. The colon system lends itself more to granularity and modularity, inheritance andsoforth. Whereas the dot system lends itself more to a stand-alone approach.

This is all in my opinion, of course and I'm very likely wrong. I'll probably be corrected by someone but that's how I've always used it. When I don't need to use something granularly, I don't pass self. In fact, in a lot of my AddOns I only pass self where I'm actually using self. I use a combination of dots and colons, to put it succinctly.

-- Edit --

Anduin's Latest I've used LuaPad to replace both AddOnObj.Func() and AddOnObj:Func in game and neither has ever thrown an error, AFIAK.
__________________
There can only be so many ways of doing things; rope rubs against rope and it causes fire, fire cleanses all. Sadly, the ropes can't be around to appreciate it.

Short: Tolerance FTW?
  Reply With Quote
11-28-05, 05:14 PM   #9
Cairenn
Credendo Vides
 
Cairenn's Avatar
Premium Member
WoWInterface Admin
Join Date: Mar 2004
Posts: 7,134
*pokes Rowne*

You should be in channel! They're discussing it in there, too, and not all of it is getting transferred over to here.
__________________
“Do what you feel in your heart to be right — for you’ll be criticized anyway.” ~ Eleanor Roosevelt
~~~~~~~~~~~~~~~~~~~
Co-Founder & Admin: MMOUI
FaceBook Profile, Page, Group
Avatar Image by RaffaeleMarinetti
  Reply With Quote
11-28-05, 05:20 PM   #10
Rowne
A Fallenroot Satyr
 
Rowne's Avatar
AddOn Author - Click to view addons
Join Date: Sep 2005
Posts: 26
I'm not an IRC person for discussing. I get too hot-headed and I don't want that to happen, here I can take my time, be calm and center myself because I really am trying to promote the "being excellent to each other"-ness of WoWI and wowace.com. Before these two communities I never had an excuse to do so, talk about bitter. Now I do and I'll be damned if I'll say a bad word to anyone.

I'm IRC for coding help and friendly natter along with goofing off, discussion? It never works for me. Whatever's presented here though I'll do my very best to impartially reply to.
__________________
There can only be so many ways of doing things; rope rubs against rope and it causes fire, fire cleanses all. Sadly, the ropes can't be around to appreciate it.

Short: Tolerance FTW?
  Reply With Quote
11-28-05, 05:34 PM   #11
AnduinLothar
Nobody of Importance
 
AnduinLothar's Avatar
AddOn Author - Click to view addons
Join Date: Oct 2005
Posts: 95
Originally Posted by Rowne
Anduin's Latest I've used LuaPad to replace both AddOnObj.Func() and AddOnObj:Func in game and neither has ever thrown an error, AFIAK.

Hmm, you're right. I just tested it and both methods work fine... odd. I could have sworn they used to throw errors... good to know i spose.

Last edited by AnduinLothar : 11-28-05 at 05:38 PM.
  Reply With Quote
11-28-05, 05:37 PM   #12
Rowne
A Fallenroot Satyr
 
Rowne's Avatar
AddOn Author - Click to view addons
Join Date: Sep 2005
Posts: 26
Perhaps it was a previous version of the Lua parser? The Blizzard devs actually stay pretty up to date with Lua and in a recent patch, they bumped it up to 5.0, which is the latest. Let's just hope they include stdlib, next.

--- Edit to Remove the Edit that was previously Edited to include a reply to an Edit which is now a Post that isn't an Edit ---

... sorry, I couldn't resist.
__________________
There can only be so many ways of doing things; rope rubs against rope and it causes fire, fire cleanses all. Sadly, the ropes can't be around to appreciate it.

Short: Tolerance FTW?

Last edited by Rowne : 11-28-05 at 05:45 PM.
  Reply With Quote
11-28-05, 05:39 PM   #13
AnduinLothar
Nobody of Importance
 
AnduinLothar's Avatar
AddOn Author - Click to view addons
Join Date: Oct 2005
Posts: 95
While I've got your attention Rowne. Mabe you want to comment on a page I've been writing. Perhaps you want to move discussion of it to another thread tho: http://www.wowwiki.com/Hooks

*hopes this doesn't derail OO conversation*
  Reply With Quote
11-28-05, 05:45 PM   #14
Rowne
A Fallenroot Satyr
 
Rowne's Avatar
AddOn Author - Click to view addons
Join Date: Sep 2005
Posts: 26
I'll take a peek in there momentarily. On the subject of hooks, Iriel raised some damned good points recently that're currently being addressed by cladhaire in Ace. It seems that we could all use a better understanding of how hooking works. I'll take a peek in there then but perhaps cladhaire would be the better choice to voice upon that subject, as, as I said, he's got position as the current Ace hooks expert. I'll pass it along.

Also, on an unrelated note, good work on IsMounted. That's one I have particular interest in and if I ever write an AddOn that requires mount checks, I'll include that as a dep. My standards are unusually high at the best of times and my standards also say, s'good work.
__________________
There can only be so many ways of doing things; rope rubs against rope and it causes fire, fire cleanses all. Sadly, the ropes can't be around to appreciate it.

Short: Tolerance FTW?
  Reply With Quote
11-28-05, 06:07 PM   #15
Iriel
Super Moderator
WoWInterface Super Mod
Featured
Join Date: Jun 2005
Posts: 578
I'm all for using OO for encapsulating grouped functions, especially if they have some shared state to maintain. It's ESPECIALLY useful if you're augmenting frames with some of your own functions, and with LUA's metatable mechanism there are some neat tricks you can use to do it cleanly,
  Reply With Quote
11-28-05, 06:12 PM   #16
Cairenn
Credendo Vides
 
Cairenn's Avatar
Premium Member
WoWInterface Admin
Join Date: Mar 2004
Posts: 7,134
Originally Posted by Rowne
I'm not an IRC person for discussing. I get too hot-headed and I don't want that to happen, here I can take my time, be calm and center myself because I really am trying to promote the "being excellent to each other"-ness of WoWI and wowace.com. Before these two communities I never had an excuse to do so, talk about bitter. Now I do and I'll be damned if I'll say a bad word to anyone.

I'm IRC for coding help and friendly natter along with goofing off, discussion? It never works for me. Whatever's presented here though I'll do my very best to impartially reply to.
Understood, respected and appreciated. Thank you.
__________________
“Do what you feel in your heart to be right — for you’ll be criticized anyway.” ~ Eleanor Roosevelt
~~~~~~~~~~~~~~~~~~~
Co-Founder & Admin: MMOUI
FaceBook Profile, Page, Group
Avatar Image by RaffaeleMarinetti
  Reply With Quote
11-28-05, 06:14 PM   #17
Rowne
A Fallenroot Satyr
 
Rowne's Avatar
AddOn Author - Click to view addons
Join Date: Sep 2005
Posts: 26
Iriel Indeedy, Tem's been going over the neatness of metatables, in fact, I'd like to learn more about that myself. There has been talk of hosting some classes in regards to metatables, lessons on how they work and all. I should pester Tem about that again, I really should.

Anyway, I agree with you. My main point was that an AddOn should be comprised of only one constant and if you're grouping functions which share variables or other things with each other, then it's a good idea to toss self around. If you're not calling other functions of the base table or not using any of the variables of the base table, then it's better not to send self because it's not required.

I think my main problem is with the global namespace usage, really. One non-Ace author I've been really impressed with lately is Silver, the AddOns are clean and they're all tabled, making only a singular hit on the namespace.
__________________
There can only be so many ways of doing things; rope rubs against rope and it causes fire, fire cleanses all. Sadly, the ropes can't be around to appreciate it.

Short: Tolerance FTW?
  Reply With Quote
11-28-05, 06:16 PM   #18
Legorol
A Cliff Giant
AddOn Author - Click to view addons
Join Date: Jul 2005
Posts: 79
If you guys don't mind, let me play devil's advocate here a little bit. Does anyone know if there are any performance implications to storing all functions and values in a table, as opposed to in the global namespace? Doesn't this result in two lookups per call instead of one?

I agree that the encapsulated method allows for cleaner code. However, as long as all global functions and variables are prefaced with the AddOn's name (as is the standard practice), isn't the chance of a collision exactly the same as with the encapsulated method?

If one wants performance, does using local functions and variables as opposed to encapsulating in a table gain anything?

In summary, apart from cleaner looking code, I'd like to know what exactly are the advantages/disadvantages of the following three ways of declaring a function:

Code:
function MyAddOn_SomeFunction()
  ..
end
Code:
MyAddOn = {
  function SomeFunction()
    ..
  end
}
Code:
local function SomeFunction()
end
If you are just worried about naming collision, the first two have the same chance of a collision (in my opinion), and the third one is better as it eliminates collision. If you are worried about performance, is the third one the best?
  Reply With Quote
11-28-05, 06:26 PM   #19
Rowne
A Fallenroot Satyr
 
Rowne's Avatar
AddOn Author - Click to view addons
Join Date: Sep 2005
Posts: 26
The only problem there however is that you're excluding your AddOn from external use. Turan and I had a little chat a while back about local functions inside major functions versus self-held functions inside major functions and I ended up agreeing with him that if the local function that does anything that changes how the major function behaves in any mentionable way, then it should be a self function, not a local function.

Why?

The reasoning is that if you use a self.func, any other user can then call that func in their AddOns, they can use yours as a dependency, which proves to be really handy. Often I've looked at code and wished that they hadn't used local functions because that means that I can't work with their AddOns, their AddOns are isolated from the rest of the user/developer's resources. Further, if I want to change how an AddOn works a tiny bit, if they were globally accessible I could hook or if it's tabled based, I could just override the table entry as talked about previously.

As far as tabling goes, it's actually pretty efficient because Lua is just that incredibly smart with tables, there's next to no overhead for even an incredible amount of tables, you could go 20 tables down and the overhead would be infintessimal as I gather. There's been talk about this on the wowace.com forums, both Tem and Turan talked it over and there were tests done. So I don't think that from a performance standpoint, it really matters. This is just my opinion, however.

Summarizing: Locals are nice from one point of view but you're not opening your AddOn up to community potential by using them. Moreover, Lua seems to be so ... if I dare say it, L33T with tables that the overhead is unnoticable.
__________________
There can only be so many ways of doing things; rope rubs against rope and it causes fire, fire cleanses all. Sadly, the ropes can't be around to appreciate it.

Short: Tolerance FTW?
  Reply With Quote
11-28-05, 07:03 PM   #20
Legorol
A Cliff Giant
AddOn Author - Click to view addons
Join Date: Jul 2005
Posts: 79
Those are some pretty strong arguments (especially the one about being able to override any function), and you convinced me that tabling functions is the best way to go. In fact, it makes me think that having both tabled and local functions allows for the kind of private/public access differentiation that other OO languages allow, which could be handy. However, you have definitely convinced me that for most applications and functions, the tabled solution is the way to to.
  Reply With Quote

WoWInterface » Developer Discussions » General Authoring Discussion » OO initiative.


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