View Single Post
07-23-12, 04:40 PM   #13
Phanx
Cat.
 
Phanx's Avatar
AddOn Author - Click to view addons
Join Date: Mar 2006
Posts: 5,617
An addon is something that users can use directly. It does something -- either changes how something looks or acts, or gives them something new to use.

A library is something that users can't do anything with directly, and can't even tell is running because it doesn't change how anything they can see or use looks or acts. It only changes how something acts for addons or gives addons something new to use.

In terms of how WoW sees them, there is no difference. It's purely a difference of how the code interacts with users and other addons.

Imagine that you have Notifications v1.0 right now, and Addon A and Addon B both use it, and include it in their downloads. Addon B changes some Notifications settings.

Already anyone who is using both Addon A and Addon Z will notice a problem -- the custom settings defined by Addon Z for its notifications also affect Addon A.

A proper library would keep a separate instance of the settings table for each addon. Two easy ways to do this:

(a) Send the addon's custom settings along with the message:
Code:
lib.defaults = {
    r = 1,
    g = 0,
    b = 1,
    scale = 4,
}

function lib:SendNotification(message, settings)
    frame.text:SetText(message, settings.r or defaults.r, settings.g or defaults.b, settings.g or defaults.b)
    frame:SetScale(settings.scale or defaults.scale)
end
(b) Send the settings once per addon:
Code:
lib.defaults = {
    r = 1,
    g = 0,
    b = 1,
    scale = 4,
}

lib.addonSettings = {
    ["MyAddon"] = {
        r = 0,
        g = 0,
        b = 0,
    },
}

function lib:SetCustomSettings(settings)
    local addon = DoSomethingToGetTheAddonName()
    lib.addonSettings[addon] = settings
end

function lib:SendNotification(message)
    local addon = DoSomethingToGetTheAddonName()
    local settings = lib.addonSettings[addon] or defaults

    frame.text:SetText(message, settings.r or defaults.r, settings.g or defaults.b, settings.g or defaults.b)
    frame:SetScale(settings.scale or defaults.scale)
end
Both methods will fall back to the default settings if the addon doesn't specify overrides.

Now imagine that you release Notifications v1.1 that adds some new features, and Addon D uses it -- including the new features -- and includes a copy in its download.

There are two big problems you can run into here:

(1) If Notifications is a separate folder in the AddOns folder, and the user installs Addon D first and then Addon A, they will end up with only Notifications v1.0 -- and when Addon D tries to use the new features that were added in v1.1, an error will be triggered because those features don't exist in the copy of Notifications that exists on the user's system. This can happen even if the user is vigilant about updating their addons, or if they install a "new" addon that comes with an older version of Notifications.

(2) If Notifications is bundled inside each addon's folder, you will still have issues. On most file systems, addons load in alphabetical order. This means that Addon A will load first, and then Addon D, and then Addon Z. If you don't have proper self-updating code in Notifications, then v1.0 from Addon A will load, and then v1.1 from Addon D will load and overwrite v1.0, but then v1.0 from Addon Z will load last and overwrite v1.1 -- and when Addon D tries to use the new features that were added in v1.1, an error will be triggered because those features don't exist in v1.0.

LibStub solves both of these problems (though not the shared settings issue):

(1) Addon A loads with Notifications v1.0, which says "hey LibStub, I'm a library, my name is Notifications, and I'm version 1.0, please load me!". LibStub checks the log, and then says "okay, no library named Notifications has checked in yet, so you're loaded!". Notifications v1.0 is now available for addons to use.

(2) Addon D loads with Notifications v1.1, which says "hey LibStub, I'm a library, my name is Notifications, and I'm version 1.1, please load me!". LibStub checks the log, and then says "okay, you're a new model, that old one has been to the scrap heap, welcome aboard!". Notifications v1.1 is now available for addons to use, and has replaced Notifications v1.0.

(3) Addon Z loads with Notifications v1.0, which says "hey LibStub, I'm a library, my name is Notifications, and I'm version 1.0, please load me!". LibStub checks the log, and then says "no way, you're a crappy old model, you're obsolete, get out of here!". Notifications v1.1 remains available for addons to use.

Addons don't have to worry about checking the library version. They just use LibStub("Notifications") instead of Notifications, and they will auto-magically get the latest loaded version of the library.

Libraries don't have to worry about including their own version checking; LibStub takes care of it for them.

You can write your own versioning code (see ChatThrottleLib) but there's not really any point. LibStub is a mere 25 short lines of code, and 99.9999999% of users will already have LibStub on their system, so including it is basically zero-cost.
__________________
Retired author of too many addons.
Message me if you're interested in taking over one of my addons.
Don’t message me about addon bugs or programming questions.
  Reply With Quote