> 2. Library Approaches
There are generally three different approaches which can be taken to use a library of common modules in several AddOns:
AddOn Dependency
The first approach is to put all of the common code into an AddOn of its own, which can then be downloaded and distributed along with the AddOns it supports. This is typically the approach taken by large compilations in which the AddOns that use the library are managed together as a single unit. The key attributes of this approach are as follows:
Explicit Bundling
The library code is represented to the user as a single bundle, and the dependency relationship between the AddOns that use it, and the library itself is explicitly documented in the .toc files.
Single Instantiation
Only one instance of the AddOn can be present, because it's represented as an AddOn with a specific name, and so there are no worries about multiple copies of the same code or Frames being generated. AddOn libraries which need XML provided resources (key bindings, or XML-driven Frames) are often best suited to the approach for this reason. This also ends up being the biggest weakness of the approach (See next)
Poor Versioning
Since only one instance of the library can be present, support for multiple versions of the library is very weak. Backward compatibility with older versions CAN be provided explicitly, but requires that the installed version is the newest one. The only choices available to an AddOn that requires a newer version of the library than the one installed are to disable itself, or potentially fail.
Dependency Stigma
There's a certain amount of reluctance from users to have to download and manage multiple AddOns just to use a feature. Excepting those who get their AddOns as a large multi-AddOn package, users will usually go with stand-alone AddOns, rather than those with dependencies. Coupling this with the point above, there are fairly good reasons why this approach is bad for the more lightweight libraries.
Embedded Library Copy
The other 'simple' approach to embedding a library is to give each AddOn which requires it a private copy of the library, either as a lua file which loads before the rest of the AddOn, or just by cutting and pasting the appropriate functions into lua files. This is of course extremely simple (with possible exception for AddOns which explicitly load other AddOns), and has the following attributes:
No Versioning Issues
Every AddOn gets the version of the library that it was developed against, so there's never any worry about conflicts between multiple users of the library. Similarly, derivative authors can alter the library functions in their copy without breaking all of the other AddOns that use the standard version (or different derivatives) of the same library.
Simple for All
There's a lot to be said for simplicity, and from both the author's and the user's perspective, this is about as simple as it gets. The author can develop in their own space, without having to worry about other instances of the library, and the user doesn't have to worry about dependencies or dependency versioning.
No Resource Sharing
All of this isolation has a downside, and the problem is that resources cannot be shared between the library instances. For small libraries of utility functions, this is unlikely a problem, but for those with some active or caching component, you can end up with lots of copies of essentially the same data. Trying to share that kind of data falls apart rapidly in the absence of a strong versioning model.
Embedded Shared Library
An embedded shared library is included in every AddOn that needs it, but each instance of the library is aware of the other instances that exist before it (and to some extent, after it) in order to remove redundant instances of the library (and in some cases, upgrade older versions!). The attributes of this approach are:
Simple for Users
This approach is just as simple as embedded copies for AddOn users, and very nearly as simple for AddOn authors who are simply using the library in their code (rather than modifying the library itself). There are no AddOn dependencies to worry about, each AddOn carries with it a copy of its own.
Shared Resources
Since the various embedded instances know about one another, they can efficiently share resources when doing so is acceptable. This goes for multiple copies of the same function(s), created Frames and event handlers, data caches, etc.
No Version Incompatibility
Incompatible instances of the same embedded shared library simply remain as separate instances (they lose the ability to share resources, but everything still works). This allows for derivative versions of the library to co-exist, and doesn't penalize users who maybe don't keep their entire AddOn set current as much as they could.
Increased Library Complexity
The cost to this approach is largely that the library must handle the versioning and resource sharing tasks when it loads. Thankfully this is something which can be addressed once with a general approach, and that is the purpose of this set of documents.
Library Author Discipline
Finally, anyone who EDITS an instance of the library must understand and follow the (hopefully very simple) versioning rules, otherwise the library may be considered compatible with a different (and not ACTUALLY compatible) version.
