Classes

This will be a very technical blog post which provides a look into the new class library which has been added to the TSM codebase with TSM4. This is an internal code library which makes it easier for us to implement new features in TSM4. This new class library is the base for many other internal code libraries in TSM4 such as our UI Builder, Database, and FSM libraries. We will go into more detail on the other libraries in future blog posts.

What is a class?

A common feature of a programming language is being “Object-Oriented”. This means that the structure of the code is based around complex data structures called objects. The type of these objects is generally referred to as their class. The class describes the structure and features of the objects.

Let’s take a TSM group as an example of how utilizing classes can be beneficial (note: in practice, TSM doesn’t use classes for this purpose). A TSM group, at its core, consists of four things: the name of the group, some sort of reference to the parent group, a list of items which are in the group, and a list of operations which are applied to the group. A user may have hundreds of different groups, but they all have these exact same attributes.

A class allows us to easily represent this structure in code and anything which is defined as part of this class will automatically be shared among all instances of the class (all groups). Having this structure also allows us to easily enforce restrictions such as not allowing specific characters in the name of a group, or only allowing a single Crafting operation to be applied to a group. This is generally done by prohibiting outside code from modifying the attributes of objects directly, but instead providing class methods which can perform this validation. For example, if I have a group object `x`, rather than changing the name via `x.name = “foo”`, I would instead call a class method such as `x:SetName(“Foo”)`. This means that there is a polished set of APIs for interacting with the objects of each class defined by the class methods. Below is an example of how this might look in pseudo-code:

` ` `

define class TSMGroup {

   string name;

   class parentGroup;

   list items;

   list operations;

 

   function SetName(string newName) {

       if (newName.contains(SOME_INVALID_CHARACTER)) {

           return false;

       }

       self.name = newName;

       return true;

   }

}

 

// create a new group

group = new TSMGroup();

group:Setname(“My Group”);

` ` `

As you can see, we can use classes to define exactly what a TSMGroup is and what methods it supports, and then create objects of that class (aka. instances of the class) which behave according to the class definition.

TSM’s Class Library

Lua, the programming language used for WoW addons, is not generally considered an object-oriented language in that it doesn’t natively support classes. However, through something called metatables and metamethods (which I won’t go into great detail on here), we can extend the language to support them. The class system implemented by the class library in TSM4 does not support every feature that traditional object-oriented languages support, but it does allow for enough of them to allow us to use classes effectively in TSM.

Specifically, the TSM class library supports inheritance and polymorphism. The former means that classes can be subclassed to extend the functionality. For example, a TSMImportedGroup class could be a subclass of the TSMGroup class and could be used as part of the import process to represent a group which came from an import string that has additional methods ontop of those defined by the base TSMGroup class. With support for polymorphism, code can be written in a way which it can operate on an object which may belong to either a class or subclass without needing to explicitly know which is the case. For example, the `SetName()` method may be called on a TSMGroup object or a TSMImportGroup object without the calling code needing to know the type of the object is calling the method on. The TSMImportGroup object can even override the implementation of SetName() if it wants to impose additional restrictions on the name of the group for example.

In the future, I’d like to add support for access restriction to the class library so that the use of proper APIs when interacting with objects can be enforced.

Digging Deeper

There is a lot more to the TSM class library. If you want to see the code, you can check out the implementation and some unit tests here.