Thread:Extension talk:PhpTags/Designing APIs in PhpTags extensions: limitations and best practices

Currently I'm developing a new extension, for which, in turn, there will be an interface in the next PhpTags SMW version. This has led to some questions which I think are more general.

The new extension defines a set of classes that are used together. The first question is: should a full wrapper for this API be made for use with PhpTags, or something simpler and more limited? I don't yet know which would be best theoretically (perhaps a simpler interface makes sense anyway) – but in practice, currently it would become much more complex to make a full wrapper. This leads to the second question, that of an idea for a possible PhpTags feature.

When making a PhpTags wrapper for a more complex OO API, new problems arise which the wrapper extension must deal with. What is simple when each class is used by itself requires more when classes use instances of each other. For every method which returns instances of a class, the wrapper must instead return wrapper objects. And for every method which receives instances of a class, the wrapper will receive wrapped objects and must handle these to pass on the original objects to the original API. This requires extra code, especially if arrays containing class instances are parameters and/or return values.

It would become simpler if there was a way to make PhpTags handle the wrapping and unwrapping of certain classes automatically. The idea is this: Currently, in PhpTags extensions there is a mapping between class names as used in PhpTags and the classes that implement them. I wonder, could the possibility also be added to similarly set a mapping between non-PhpTags class names and the corresponding PhpTags extension classes that wrap around them? For automatic "translation".

The idea would be that the first time a non-PhpTags object is handled in a PhpTags expression, if such a mapping exists for the class name, then PhpTags would automatically construct the wrapper object and make it usable. Then the wrapper object would be used for all access to the object's members and methods. At the same time, in such cases, the original object would still be passed around on the PHP level. So any functions or methods which receive the object as an argument would receive the original object instead of the wrapper object. (And likewise if they receive e.g. an array containing the object.)

I don't know if this would be too difficult, or cause too great a performance overhead. If not, then it could actually make for better performance for complex APIs. In the methods in a PhpTags wrapper class, there would be no need to, say, reconstruct arrays of objects to change between the original objects and wrapper objects. If the original API returns an array with original objects, then the wrapper can simply return this, instead of a new array with wrapper objects. Likewise, when the wrapper receives an array with objects, they will be the original objects instead of wrapper objects, and the array can therefore be passed directly to the original API.

Even without such a feature, simpler APIs are still easy to support in a PhpTags extension. I don't know how simple or complex the feature might turn out to be to implement, nor how generally worthwhile it would be. However, if added, I think it would make it much easier to support more complex APIs in extensions for PhpTags.