Ruminations on API 2.0

I took some time this week to really work with API 2.0.  I took a generic ActiveRecord project and converted it to the new API.  It wasn’t long before I found a showstopper bug with DateTime and Introspection (it has since been fixed in a beta).  There were only a thousand or so “Deprecations with Replacement” message so that was just a few hours of work.  Many were duplicates of the same bug (since I use a lot of arrays in ActiveRecord the Append method needs to change to AddRow).  Fairly easy to change if not repetitious.  No big deal, right?

Shorts, our reporting tool, has thousands of immediate ‘deprecations with replacements’ warnings.  And then I got into things like Recordset turning into RowSets and string functions changing.  After 5 hours of working on it I’m still at over 3,000 deprecation warnings.  At this point I just don’t see the point of trying to convert Shorts.  Obviously at some point I will have to but there is no immediate need to do so.

And that’s the problem with flagging all the old API warnings as Deprecations.  It’s kind of silly because there is no immediate need to do so.  It’s just an item marked as deprecated but will be around forever.  So I think it’s silly to call them deprecated in the first place.

Another issue I have with the list is that it’s not grouped in any functional way.  They appear in the list as they’re found by the compiler.  In my ideal world I’d like to work with all the Dates I’m converting to DateTime all at the same time.  Same with RecordSets to RowSets and so on.  The Check Project just doesn’t help when it has thousands and thousands of warnings in random order.

Some changes you can use global search and replace.  The caveat being that if you’ve added a similar method to your class you might kill your project accidentally (i.e. see Shorts above).  The other thing that really makes life hard is string manipulation.  In the old framework strings were 1-based.  In API 2.0 they are 0-based so if you were using String.Inst and checking for zero you now are using String.IndexOf and checking negative one.  There is simply no way you can do a global search and replace for that.  The other one that’s been biting me is the use of Recordset.IDXField that was 1-based.  The replacement is RowSet.ColumnAt is 0-based so that’s another thing you can’t just use global search and replace.

The 2019 R2 IDE added the ability to quickly create a #if block to separate pre-2019 R2 code with new API 2.0 code.  That works well but for large projects that might be a lot of work.  Too much work on any project of any reasonable size.  

In API 2.0 there are a lot of replacement properties and methods.  For the most part these are not a big deal.  However they don’t always make sense.  For example, the TextField and TextArea Text property have been changed to Value.  How does that make using TextFields and TextAreas any ‘easier’ to understand?  TextField1.Text = SomeVariable is perfectly understandable whereas TextField1.Value = SomeVariable is less understandable because now I need to know that I’m talking about a TextField or that SomeVariable is a string.  If you are enforcing your control naming conventions and variable naming conventions it’s not so bad, but still this seems like an unnecessary change.  It makes reading code LESS clear in my opinion.

Since the value type didn’t change (string in this case), I don’t see why this change happened.  I guess one could argue that it makes it more consistent with things like CheckBox.Value but I’d argue that CheckBox.State is the better ‘value’ property since a Checkbox can have three states.  Inconsistencies like that make API 2.0 harder to use in my opinion.

The new Event names in API 2.0 is a big deal.  Nearly every control event has new event names.  But then some like MouseMove, MouseDown, MouseUp didn’t change.  Seriously, if you are going to change the event names for practically everything why not go all out and change everything?  Which begs the question why were some changed and not others?  I digress.

Some changes like Button.Action changing to Button.Pressed actually make some sense.  There was actually confusion from new users on what event to implement.  I can’t tell you how many times I saw a new Xojo user implement the MouseDown event because it looked more promising than Action.

But some new event names are just stupid.  Timer.Action event is replaced with Timer.Run.  WTF was this for?  The Timer has one event and I could argue that “Run” is not an accurate description of what that event means.  The timer isn’t ‘running’, it’s finished running.  Maybe a more appropriate event name would have been “DoYourOneJobNow”.  This begs the question I’ve been saying for years that why do I have to implement the timer event at all?  Rarely have I ever used with without the event.

And sharing code between versions of Xojo is totally borked.  Say, I have a class written with API 1.0 and I implement the Open event and then give it to you.  You’re in 2019 R2, create a subclass of my control, and implement the Opening event (because that’s what you want to use because you don’t want those silly deprecation warnings).  However, when you do this you’ve now kept my Open event from being called.  Thus whatever I had in the Open event is no longer run.  To me this is the most egregious bit about API 2.0.  Me, as a 3rd party Xojo developer can’t control what you’ve implemented.

There are several solutions (probably more) to the events issue.  First, the compiler, in 2019 R2 and above must produce an error if both the old and new events are implemented.  It would require a compiler engineer to move up the chain and see if both old and new events are implemented in the object and then spit out a compiler error that is understandable.  Who on staff could do this?

Another solution is to alias the events so that if someone implements the Opening event it automatically calls the Open event.  One question that’s not answered yet is:  Do we know if API 2.0 events fire in a different order than the old API 1.0 events?

Another solution that I’m pretty sure Xojo will not do is revert the events back to pre-API 2.0 status.  This solves all of the backwards compatibility issues that the Xojo 3rd party developers have with API 2.0.  We can deal with new methods using the #if XojoVersion technique but I don’t see how anything else is going to work and keep everyone happy.  The new API 2.0 properties in pre R2 projects could be hard to deal with so I’m not sure the best way of dealing with those since any flags put in for R2 won’t work in pre-R2.

In general, I think API 2.0 is a hot mess.  You don’t HAVE to upgrade your project to API 2.0 and I highly recommend that you do NOT for the foreseeable future.  I have not migrated any existing clients to R2 and have told clients that do their own development to not upgrade as well.  The API 2.0 saga is not finished by a long shot and it will take a while resolve itself (hopefully).