@jotter I think you also miss the use of VARIANT as wholly unhelpful
A person could pass in an integer - and the method call would compile and fail spectacularly at run time
Pushing errors out to runtime is probably one of the worst things about this design
The earlier you catch errors the better
Catch them at design time they are easy to fix - no code written yet
Change the design
At compile time - well not perfect but no code has shipped
But at runtime its way too late !
I’m sure I hear the
Oh but just TEST the type at runtime to make sure its a Graphics or WebGraphics !
So now the code is
#If TargetDesktop Or TargetMobile Then
if (context isa graphics) = false then
return
end if
Var g As Graphics = context
#EndIf
#If TargetWeb Then
if (context isa WebGraphics) = false then
return
end if
Var g As WebGraphics = context
#EndIf
That still leaves the issue as a RUNTIME one
and the CALLER is 100% unaware that their call has failed when passing the wrong parameter type (ICK !)
The compiler cant help you at all (which I personally think is a huge downfall)
An interface would certainly make life a bit easier - at least the graphics & web graphics would present a similar API
Variants subvert the type subsystem in Xojo and should be avoided so the compiler CAN help warn about wrong parameter types, type mismatches etc
Having to resort to them for this code is great example of a bad design leaking into the wild where you have no choice but to deal with that bad choice
3 Likes
Something you MIGHT consider is writing your own wrapper class
So DrawBoard looks like
DrawBoard(context as MyWrapper)
And calls to it are like
Var cb As New Checkerboard
dim wrapper as new MyWrapper(g)
cb.DrawBoard( wrapper(g) )
cb.DrawCheckers(wrapper(g) )
MyWrapper then can have one constructor for Web and one for Desktop (thanks to compatibility flags)
the web only constructor
Public Sub Constructor(g as webGraphics)
instance = g
End Sub
the desktop only constructor
Public Constructor(g as Graphics)
instance = g
end
Instance might be a variant property internally (not exposed to the world)
And then the MyWrapper exposes the various drawing methods of whatever it got called with
Sub DrawingColor(assigns c as Color)
#If TargetDesktop Or TargetMobile Then
Var g As Graphics = context
#EndIf
#If TargetWeb Then
Var g As WebGraphics = context
#EndIf
g.drawingColor = c
end sub
function DrawingColor() as color
#If TargetDesktop Or TargetMobile Then
Var g As Graphics = context
#EndIf
#If TargetWeb Then
Var g As WebGraphics = context
#EndIf
return g.DrawingColor
end function
and so on
At least this way YOU can provide some consistency by wrapping it however you want
And the compiler can help you out by flagging erroneous calls and usage
1 Like
For their Example Project it would be enough to just use the Constructors approach (without the overhead of the Wrapper class - you know… they’re marketing for “citizen developer”, not more experienced ones
).
Class 'Checkerboard':
Public Sub Constructor(g As WebGraphics) // Include in Web only, Public
context = g
End Sub
Public Sub Constructor(g As Graphics) // Include in Desktop and Mobile, Public
context = g
End Sub
Private Sub Constructor() // Private, so you can't instantiate without Parameter
End Sub
And I’d also change the conditional compilation parts… What if at some time it’s neither TargetDesktop
, TargetMobile
and also not TargetWeb
? Not good enough to just check with #If
for a single case.
#If TargetDesktop Or TargetMobile Then
Var g As Graphics = context
#ElseIf TargetWeb Then
Var g As WebGraphics = context
#Else
#Pragma Error "Unsupported Target"
#EndIf
Oh well… I guess we all have ideas and suggestions how to do better.
All I wanted to point out on TOF is that providing such example projects (and even marketing them via Blog…) doesn’t look good for them 
5 Likes
Variants are so bad in these situations. Feels like typical Xojo ‘solution’ though.
3 Likes
THIS!!!
On the other hand… have you expected something else?
Let’s wait till the first comes around and offers an Addon to sell…
1 Like
I ran into this exact same issue with one of their blog posts, and this was pretty much the same answer, it’s just an example of how it could be done.
new users are going to think
This comes from the CEO. He MUST know what he’s doing
and run with it as if its great code
And this sort of thing sets them on a bad path
1 Like
and don’t forget any AI parsing through their side and learning BS
Personally I feel the approach discussed is bullshit.
It is better to integrate and use Skia for cross platform drawing functions.