Is Pro+ worth it ?

I’ve now had use of a Pro+ license for nearly a year.

When this license type was introduced Xojo told us that the Pro+ included

Top Priority Support is just as defined on that page, we’ll bump your support questions to the top of the queue and we’ll review your Feedback cases first. And of course you can set up a call with us anytime too.
Fast Fixes is as defined on that page as well. Because of the difference between bugs and what may be involved in fixing one, we can’t promise that we will fix “X” bugs for you. But we can promise to help you track down an issue in your code, get a bug you’ve discovered fixed more quickly or help you find a workaround.
And yes, we did previously offer a meeting with Geoff but people did not seem to want or use this so we dropped it. Geoff is always interested in hearing from customers, if you want to reach out to him on the forum you can anytime. Or email hello@xojo.com to set up a call.

https://forum.xojo.com/conversation/post/429116

So far my experience is that this is a nice statement but the reality is different. As I write this I still have several cases awaiting review – some for several months

I’ve actually had to ask about getting these reviewed more than once yet there they still sit.

What Top priority support meant wasn’t clear to me what that meant so I sent an email asking

On the page for Pro+, which I now am a holder of (designated), it says Top Priority Support.
We understand that some Xojo users need support issues resolved ASAP. With Xojo Pro Plus, you’ll get support questions answered first and bug reports will be verified first.
Is that for all reports I submit while I hold the license ? Or just ones I specifically bring to your attention ? Thanks

https://forum.xojo.com/conversation/post/429116

And the reply was

Hi Norman,
Pro Plus users cases are automatically flagged in Feedback, so you don’t have to do anything. A case is also flagged if you add your name to it, so you don’t have to be the creator. To be clear, it does not mean we will fix it right away, but it will receive a higher priority. If you encounter anything show-stopping please reach out and bring that to our attention so we can look into it.

I pointed out that I had several cases that had been sitting and I also wrote back saying

I’m not expecting that it will be fixed right away

I just have a number of cases that are still in the Needs Review state and have been for a couple of weeks at least

And got a reply saying

Ok, we’ll take a look.

That was in August and most of these cases have remained in the Needs Review state since then.

In Nov I again asked about the reports still in the Needs Review status and was informed that they would endeavour to get caught up. To date they are not. Some are marked reproducible, some reviewed and some still needs review.

The other thing mentioned in the post is “Fast Fixes” but it was unclear on how many are included with a Pro+ license. So I posed that question and was told

There’s no set number that is listed but 2 per year is what I would work off of.

I haven’t asked to use any of the ones included with the license I’ve been assigned but not having a number stated as part of the license is bothersome to me. Is it more for some customers and fewer for others? Does it depend on the nature of the Fast Fix itself? And what are the criteria for what is and isn’t a Fast Fix?

I certainly can’t answer that. Xojo also wasnt cleear on what might qualify as a Fast fix.

The last item in the list is being able to schedule a call with Geoff. As of today I have an outstanding request to schedule a call with Geoff. So far that has not been scheduled nor have I had any indication that it will be. The email reply I got back made no mention of scheduling a call and focused entirely on other issues unrelated to my request for a call with Geoff.

In my opinion I’m not seeing that holding a Pro+ license actually makes any difference in how fast the reports I file get reviewed or fixed, or that it has any influence on any of the other aspects it claims to have influence over. (1) As of this writing ~60% of my cases are “Open” – either needs review (29 of 396), reproducible (88 of 396), reviewed (92 of 396), or verified (15 of 396).

If I were making a purchasing decision today I would opt for a Pro license. I might get 2 of them if I really needed twice as many installs (Pro+ includes 2x installs). I would save the extra $600. Xojo could alter the Pro+ to permit 3x activations and remove this as a consideration for opting for multiple Pro licenses instead.

Things don’t actually seem to move along any faster because its a Pro+ user reporting it or not.

YMMV. Anyone else have a Pro+/Enterprise license and have anything different to report ?

 

(1) Note this could be simply because I am who I am and Xojo does seem to treat me differently than other customers. I cannot say why they do this. It just seems to occur and others have mentioned they notice this difference to me.

Programming thought experiments

Some companies like to pose certain programming questions as part of their interview process.

I’ve run into a variety of these. They’ve been SQL related questions, code writing, and algorithm descriptions. Some were fairly straight forward. Some less so.

One of the best I heard was a series of “How would you write this code if you had to write it …” with varying restrictions put on things. And the code was pretty simple. Write code to count all the upper and lower case letters in a string of ASCII characters.

First write the code however you wanted. Loops, if then else, select case.

Depending on which branching style you used the first time then the follow on was to write it using the other. If you first used a massive if then elseif statement then switch to using a select case.

And of course take into account that Xojo IS not case sensitive with string comparisons.

And finally to not use a branching type at all. This requires some out of the box thinking. Literally “count all the upper and lower case ASCII letters without the use of IF, SELECT or any other branching control.” All you have to use is a loop (while/wend, for/next whatever you wanted)

This first two bits are fairly straight forward.

The third however is still one of my favourite “thinking out of the box” approaches.

Anyone care to take a guess at how to achieve that one ?

32 bit apps in a 64 bit era

MacOS has been fully 64 bit since the release of 10.7 (Lion) in 2011.

Yet is has continued to support running 32 bit apps up until the release of 10.15 (Catalina) which removes support for 32 bit apps entirely.

There are ways to work around this like running an old version of macOS in a VM.

There are many apps that have not been updated for 64 bit. Things like AccountEdge (what used to be MYOB) wont be updated to be 64 bit. Old versions of MS Office need to be updated to newer ones as they too are 32 bit and will not operate on Catalina.

And anyone producing apps in Xojo should be building ONLY for 64 bit macOS. I’d encourage that even if you have to support old versions of macOS since all versions that Xojo supports are all 64 bit.

If you’re still building for 32 bit macOS you should update now and be building for 64 bit.

I’d encourage you to do the same for Linux as most modern distros are 64 bit.

The only target where you might need to still build a 32 bit and 64 bit version is Windows where you can get both 32 and 64 bit versions. While most machines sold today are 64 bit and installing a 32 bit OS on them doesn’t make much sense there may be legacy machines running a 32 bit version.

MacOS plists

Xojo includes the ability for you to supplement the plist a macOS build creates.

You can’t overwrite the items the IDE will generate for you but you can add things like heys for App Transport security, Crash on Exceptions and even your own custom items if you want them.

The entire of creating and adding a plist is fairly simple.

Start a text editor. Notepad, textEdit, BBEdit or whatever one you happen to use (vi, emacs, nano, etc will all work just as well)

Make sure you create a “proper” plist that includes the normal header and footer. its just an xml file. The basic form is as follows :

<?xml version="1.0" encoding="UTF-8"?>
<!DOCTYPE plist SYSTEM "file://localhost/System/Library/DTDs/PropertyList.dtd">
<plist version="0.9">
<dict>
    <!-- your additions go here -->
</dict>
</plist>

Then you do need to look up the specifics of whatever key it is you’re adding and how it should be written.

The really lazy way is to open Xcode and use its built in plist editor by selecting File > New File > macOS > Property List and then saving the file. But for folks on other OSes thats not going to work.

A lot of the keys like Crash On Exceptions are booleans which are written as

<key> THE KEY NAME HERE </key><true/> 

or false instead of true if the item should be off. Others like Apple Event usage are strings as follows

<key>NSAppleEventsUsageDescription</key><string> YOUR DESCRIPTION OF WHY YOU NEED TO USE APPLE EVENTS HERE</string>

There are LOTS of possible keys that can be in a plist. Adding them at build time can make a tedious process a bit simpler.

Lies. Damned Lies. And Pragma Unused.

Lots of times we might like to clean up our code by making sure we fix all the errors AND all the warnings as well.

And one of those you might find you get warned about is unused parameters. These might come about from implementing some interface for a nice consistent API but some implementors of the methods on the interface dont use all the parameters.

You can go around and read each warning and selectively insert

#pragma unused <whatever one the compiler warned you about>

Or you can actually be lazy and lie to the compiler and kust copy and paste all the method parameters and put a #pragma unused for each parameter. The compiler wont give you a warning or error about having lied to it even if you DID use the parameters after you said it was unused.

For example if you wrote a method like

Sub foo( bar as integer, baz as integer)
   #pragma unused bar
   #pragma unused baz 

   dim i as inteher = bar + baz
End Sub

the compiler will happily accept this and not warn about bar or baz as being flagged as unused

Have fun !

The nature of the change

I’ve seen lots of discussions that talk about how certain bugs have been copied over from API 1.0 to API 2.0.

This is unlikely and mostly not correct. From what I can tell nothing was “copied” from one API to another.

Let me detail why I think this is the case with an analogy.

Suppose you had source code that you could compile into a dynamic library for macOS (a dylib), Windows (a DLL), or Linux (a .so). But in your Xojo application instead of having to write all the declares every time you wanted to call you dynamic library you created class, or module, that put a nice API on it that hid all those declares. A great example of this is something like macOSLib which hides a lot of the details of calling into macOS Cocoa API’s from you. Behind the nice Xojo API this presents are a lot of declares. But you dont have to deal with those. You just use the classes available.

Thats roughly analogous to API 1.0 – the classic API used from the days of REALbasic through to Xojo.

Now if you altered the Xojo code in all those methods and classes by renaming the properties and events in the Xojo API or added new ones, but did not alter the underlying declares, you would have a new, or modified, API. And if you brought all this code into existing projects you’d have to adapt all your existing code if you wanted to use this new API. But you would still retain all of the old bugs you had in the C++ code.

This is roughly whats happened with API 2.0

API 2.0 is a new API on top of much of the same framework that has existed for years. Hence there are old bugs still present along with new ones adding this new API has introduced.

Thats not to say the new API 2.0 work didnt alter any of the underlying code. There are some things like Folderitem which appears to have new more modern OS API’s in use on macOS (a very welcome thing) and a handful of other items.

But by and large API 2.0 sits on the same framework as API 1.0 did.

IsEventImplemented

In 2019r3 Xojo added something that a lot of people have been asking for for a very long time. A way for a class that exposes events to know IF an instance implements the event.

Its literally called IsEventImplemented (see http://feedback.xojo.com/case/58342)

But it remains undocumented

Previously if you wrote a class that could have some default behaviour IF an instance did not implemnent the event to alter the behaviour you had no way to know if you should operate in whatever way was the default or not.

You could never have your superclass do something like

If IsEventImplemented("Action") then
   // call the instance' code
   raiseEvent Action
else
   // do nothing
end if

In this case its not so bad and you could probably just use RaiseEvent without any impact. But if you wanted to do something more, like know if you should use a default color or not you had a much more difficult task

// if we had an event ChooseColor that instances could implement or not

defaultBackGroundColor = raiseEvent ChooseColor

// if setColor IS implemented we'd get a color 
// if setColor is NOT implemented we still get a color - its just all 0's
// and we have no way to know which is the case 

But now with IsEventImplemented we could know

// if we had an event ChooseColor that instances could implement or not

if IsEventImplemented("ChooseColor") then
   defaultBackGroundColor = raiseEvent ChooseColor
else
   defaultBackgroundColor = &cFF00FF // or whatever
end if

// now we can use defaultBackgroundColor knowing whether 
// it did or did not come from the instance

However, Xojo has chosen to not document this (see http://feedback.xojo.com/case/58868)

The comment almost makes it seem as if this method might disappear despite its usefulness whether API 2.0 event have or have not been reverted.

Use it carefully !

Fail early. Fail often. Fail loudly.

And by that no I don’t mean that YOU personally should fail. I’m of the same mind as my dad on that front. You should work your ass off to do the best job you know how to do. That doesn’t mean you’re perfect or that you expect perfection. There are lots of things in this world that I do not know how to do very well – but when given the opportunity I try to do the very best job I know how to and I try to learn how to do it better next time.

What I mean by the above is that your CODE should fail early often and loudly. I know some folks say “software should never fail” and thats a great goal to strive for but there are times and reasons why that is very close to impossible to prove without it being so ridiculously expensive that its just not practical for the vast majority of use cases.

And in those cases that you DO detect a failure, more than likely some exception, that you cannot handle or did not code for your code should bitch moan whine and grind to a halt immediately. Don’t try and recover from something you didn’t foresee. You may, by trying to recover from some unforeseen failure, actually cause more damage. If memory got corrupted and you try to recover you could wipe the hard drive or so something else much worse.

Personally I’m a fan of writing code in a way that it basically asserts preconditions at the beginning of the method and what inputs it expects. Some languages make this really easy to do – but you can do this in any language.

Range checks, format checks, nil checks and other checks as the first few lines of a method making sure things are the way your code expects make it easier to handle any issues that arise before you get far.

User inputs should be checked and sanitized at the point they are gathered. And if they are then your code should never get values for parameters that are unexpected (you did check ranges and such right ?????)

After that you code as defensively as you can and behave reasonably. But trying to recover from something that is a potentially fatal error (not just an out of bounds which you _should_ be able to handle in a reasonable fashion)

An unexpected runtime exception that is NOT one you anticipated SHOULD, IMHO, STOP your app right then and there and set things up in a way the end user CAN report it to you so you can fix it. It should not try to do anything else as you have NO assurance you CAN do anything else reasonable at that point.

Trying to continue on operation may well result in even more failures hat could do even more damage.

So write the best most well thought out code you can.

And when all the rest of the world and your environment is letting you down FAIL before you seriously break something else (like deleting a database or corrupting it)

And tell your user as much as you can WHY things failed.

And then fix it as correctly and quickly as you can

Rust

and other cruft starts to accumulate if you’re not careful. But thats not what this post is about.

Its literally about the programming language Rust.

It’s been quite some time since I’ve had to do a lot in C which is what Rust feels like. Full of curly braces and semicolons its VERY C like – and I’ll post about my adventures getting familiar with it and how I think it can be leveraged in a cross platform world.

It has some nice characteristics. It can compile for a wide range of targets from the get go. So far it looks like you can cross compile from macOS to Windows and vice versa (as well as many other targets) which is handy. And you can have Rustc compile exe’s, dylibs and several other types as well as its own custom types.

Looks darned fun.

Bit twiddling in a CSS age

Got a curious question the other day. One I had never really thought much about but after a discussion it became clear to me why the questions were the way they were.

Bit flipping and bit masking is not intuitive.

And unless you’ve had to do it then approaching it for the first time may no make a pile of sense.

For instance, if you have a look at the binary representation of a value in a Uint8, with code like

Dim i As UInt8 = 8
Dim s As String = Bin(i)

break

that 8, in binary, is 1000 (note I consider it a bug that any leading 0’s are not shown – they should be as the value 1000 is only 4 bits not all 8. Xojo’s Bin and ToBinary do not show it which is, incorrect, IMHO)

A Uint8 is 8 bits wide/ a Unit16 is 16 bits wide. A Uint32 is 32 bits wide. And any value stored in there uses ALL those bits either set to 0 or 1. So a 32 bit version of 8 should be

&b00000000000000000000000000001000

With this starting bit of info out of the way bit masking using the built in operators, AND, OR, NOT and XOR becomes somewhat simpler. Especially if you write things in binary using the &b notation although with really big values it becomes hard to read. This is often why you see people use HEX – or hexadecimal. It’s more compact. Octal is another form that is less often used.

If we start with our original value, 8 , as a Uint8 (or &b00001000) and want to test if certain bits are set then the AND operator is VERY useful.

In binary the LOW BIT, or bit 0, is the RIGHT MOST one – just like in decimal the ones is right most, tens next to that and so on.

So if we want to test if bit 3 is set in &b00001000 we can do

dim result as integer = 8 AND &b00001000
if result <> 0 then
  // tada ! bit 3 IS set !!!!
end if

The AND operator will take two bit patterns and match them up. Where there is a 1 in both operands, 8 and &b00001000, the result will have a 1. Since 8 is, in binary &b00001000 we get a result of &b00001000 – bit 3 is set in both 8 and so the result gets a 1 in that bit position.

     8 => &b00001000
AND       &b00001000
---------------------
          &b00001000

If we try a different value, 9, then we get results like

     9 => &b00001001
AND       &b00001000
---------------------
          &b00001000

Note the representation of 9 is basically “8 + 1”. Again when we apply the AND operator we get a result that is not 0. From that we know that in the two patterns some bits matched and gave us a result that was NOT all 0’s.

Other operators do slightly different things.

The OR operator will make sure that bits in the result are set to 1 if a bit is set to 1 in either operand. if we wanted to make sure that bit 3 WAS set then we could use OR

     8 => &b00001000       0 => &b00000000
OR        &b00001000    OR      &b00001000
---------------------   ------------------
result    &b00001000    result  &b00001000

In the left example above we started with the bit set. OR will not change it and so it remains set in the result. In the right hand example we start with the bit NOT set. OR makes sure it is set and the result has the bit set.

The NOT operator will flip all bits in the result. It only takes 1 operand. Any that are set to 1 will be flipped to be 0 in the result. Any that are 0 will be flipped to 1.

     8 => &b00001000       0 => &b00000000      170 => &b10101010
NOT                     NOT                    NOT
---------------------   ------------------     ------------------
result    &b11110111    result  &b11111111     result  &b01010101

In the left most example above we started with the bit set. NOT will change it and so is cleared result. But not also inverts all the other 0’s to 1’s as shown in the middle example. In the right hand example we start with the bit pattern for 170 (&b10101010). When we use NOT it flips every bit to the opposite.

XOR is the weirdest one. it full name is “exclusive or”. What that means it in its 2 input operands the result will be a 0 every where the inputs match. And a 1 everywhere they do not.

     8 => &b00001000        0 => &b00000000         170 => &b10101010
XOR       &b10101010    XOR      &b10101010     XOR        &b10101010
---------------------   -------------------     ---------------------
result    &b10100010    result   &b10101010     result     &b00000000

In the left most example you can see that we get 1’s in every spot where the second operand has a 1 and the first doesnt. But because bit 3 matches we get a 0 instead of a 1. The middle example shows that when one operand is all 0 you get a copy of the second operand. And in the right most we go no 1’s because all the spots in both match in every position and so we get all 0’s.

As I said writing these out for anything larger than an 8 bit value as binary is tedious and error prone. And so you often see hexadecimal used.

So how to determine the “right” hex to use ?

Again, EVERY integer is ALWAYS as the FULL width of whatever type you used. So always make sure you write things out in full.

We’ll start simple with an 8 bit value.

To convert &b10101010

  • write it in groups of 4 bits each(&b1010 1010)
  • each group of 4 bits is ONE hexadecimal “character”
  • the low bit position in the group of 4 is like the “ones” in decimal, the next like the tens and so on.
  • the lowest bit, if set, means a value of 1
  • the next bit, if set, means a value of 2
  • the next bit, if set, means a value of 4
  • the next bit. if set, means a value of 8

so in our case, &b1010, means, working from right to left, 0 + 2 + 0 + 8 or 10 * (You can check thins in Xojo code if you care to)

Now the screwy part. Our normal counting system is base 10. so whenever we get to 10 we start a new position to the left of the current one. In hexadecimal you count up to 16 – not 10. And so up to 9 things are the same but then for 10-15 we use the letters A to F (A = 10, B = 11, C = 12, D = 13, E = 14, F = 15) You convert each group of 4 bits exactly the same way.

So in hexadecimal our value is &hAA (= &b1010 1010) Again you can check this in code

if &hAA = &b10101010 then
  msgbox "Norm was right"
end if

Because hex is much more compact its widely used. And for large values its simpler to read and can be used just as effectively for bit masking. You just have to know how to convert you binary bit masks into hex.

*The number theory behind how decimal, binary, hexadecimal, octal and other counting systems works is really quite interesting. They’re all positional based systems and the difference is the base they use, not so much HOW they use the digits in the specific counting system. Heck we all use one every day that is base 60 and it seems perfectly normal whenever the minutes go by and turn into hours 😛