Hi,

The Firebird 4 is the first version that has "evolved" interfaces. This bring to table some important questions...

1. What is the official policy for evolution of interfaces? Will their version change every time they change, even if the change replaces "development" version like beta etc. ?

I noticed that iUtil interface in FB 4 beta 2 has version 4, where version in FB 3.0.5 is (base) version 2. Where is the version 3? It gets "lost in updates" over development of FB 4 (3.0->4.0 alpha). This creates "mysterious" gap in versions between stable releases that we should IMHO avoid.

On the other hand there is a precedent when interface was changed in backward incompatible way during development (and without version change). I'm ok with this as long as such changes would be properly announced in firebird-devel.

So, I really wonder what is the official policy one can rely upon? If there is one, I missed the lesson when it was given. In case there is not one set in stone, I'd like propose next for "development" versions:

If completely new interface is introduced, or interface that was part of stable release is changed, it will follow standard rules for versioning. This version will be "stable" over whole development cycle (i.e. it will be the final version for stable release), despite latter changes to it. This is supposed to be "dev" interface version and subject of change anyway, so there should be no trouble for its "users" if all changes to it will be properly documented at well known place and changes announced in firebird-devel.

2. Strange things with iUtil in FB 4.

a) Why methods getDecFloat16, getDecFloat34 and getInt128 require iStatus parameter? I expected that these methods should be "safe" like iMaster.getUtilInterface() and thus should not require iStatus.

b) Is it possible to extract time/timestamp related methods from iUtil out to separate iTimezone interface like it was done for defloat/i128 ? The iUtil is a "sink" interface prone to change, which over time would make it [a] "crowded" and [b] subject of version escalation.

3. Interface definitions in IDL file and inconsistent way for "versioning".

a) The version is derived from number of base interfaces (inheritance chain). This is completely fine approach that makes sense. In generated files it uses inheritance to construct the interface.

b) It uses "version:" tag inside interface definition to mark interface extensions. In generated file it has the same name and inheritance chain but different version and number of methods. And this is IMHO not fine.

I can understand that method [b] allows stable "leaf" interface name and keep the inheritance chain minimal over time, but it has dire consequences as the interface becomes opaque. Imagine that you have an application that can work with different versions of Firebird, that may use different interface versions. You have to use the API file for most recent one, but when connected to older versions, you have to use just the "safe" part of returned interface. Sure you have to inspect the VERSION stored with interface, but then what? How you can tell from opaque interface which methods are safe for which version? You can't, you have to know beforehand from documentation, and any mistake is fatal at RUN TIME. This problem will build up with each FB release with new interfaces. And this lead us to part 4.

4. Status of cloop-generated interface files for C++ and Pascal. If new interface-based API is the way to go now, I suppose that these files are the official standard base for end users to access the new API from these languages, right? So their quality really matters (cloop bugs aside).

I couldn't judge the C++ version, but I still understand Pascal a little, and it's clear that generated code is strictly paired with Firebird version for which is generated (due to their definition mentioned in point 3). If it will be used to access older FB version that returns older version of the interface (legal requirement), then safe use of the interface is completely up on developer. I.e. if it will call a method that is not in older version, it will crash and burn the application (in best case) without proper error handling, as the generated code doesn't handle this problem at all and lets the code crash and burn. From consumer's POV, this is IMHO not acceptable, so they would need either a better version or "real" interface library provided by someone else that solves this problem (it should at least raise an exception on illegal use).

This is not a problem for languages like Python, Java and .NET that don't use these files at all, but C++ & Pascal are still important languages and we should offer some better solution. At least it should be discussed with those who use them (for example MWA Software, developer of ibx4lazarus?).

A side note about interfaces and versioning in new Python driver for inspiration... It provides interface wrapper classes that have interface for "humans". For example they manage iStatus (and error handling) where needed behind the scenes so you don't need to bother with it at all (unless you want to). The same apply to reference counting and dispose for relevant interfaces. They converts data between Python and C interface for you, saving you from some unneeded parameters like buffer and string sizes that it could handle itself etc. When it comes to interface versions, they use inheritance properly and a little bit of meta-class magic to provide you with wrapper that matches the interface version returned, so you can't call illegal methods at all and can use either intf.version, isinstance() or hasattr() checks to branch your code easily on version or method basis.


best regards
Pavel



Firebird-Devel mailing list, web interface at 
https://lists.sourceforge.net/lists/listinfo/firebird-devel

Reply via email to