Hello everybody,
The question I have concerns
OSWindow and its backend : SDL.
However, even if I'll speak
about these two, i think the
question is quite general and
can apply to every API.
There are some functions that we are
sure we will find in every backend
possible (for instance the
possibility to create a new window,
to resize it etc.) and for these
ones it is totally fine to abstract
the backend from the user because
you know that even if the backend
has to change the API will be usable
the same way.
But there are some functions that are
quite specific to a certain backend
and you cannot always find it in
others. But this function is cool so
it would be a shame not to implement
it just for the sake of uniformity.
In this case I see two options :
1) You abstract these functions exactly
the same way you did for the others and
the user is not informed at all. In this
case the risk is that if the backend
changes it may break the API for the
user because he won't be able to use
this function anymore.And he may feel a
bit sad because he was not warned about
it.
2) You make
something to
let the user know that this or that function
is specific to this or that backend. By
doing so the user knows that there is a
small risk that he won't be able to use this
function anymore if the backend changes. He
has been warned.
Now I prefer the second option but I wanted to
ask you about that "something". What is the
best way to warn the user ?
- Should I let the name of the backend in the
name of the method ? "SDL_MySpecificMethod"
- Should I put all these methods in a specific
package and name / comment that package
accordingly ?
- Some other things ?
Basically my question is : what is the best way to let
the user know he is dealing with a specific function
for a specific backend ?
Thanks,
Matthieu
A recent idea I had, translated to your case, was
doing this by providing accessors to specific backend extension
classes.
Personally, I'd prefer to use a class separate from
that which implements the common interface, so one doesn't
accidentally end up doing common calls on only specific
backends, here's a purely theoretical example of how that may
look:
window := OSWindow new.
window title: 'Test window'.
"With SDL, we support making window unbordered"
window SDL bordered: false.
window openInWorld.
With a few example implementations:
OSWindow >> #SDL
"Could cache in instvar, but that would not as
modular, as you can't package that with the rest of the backend,
with methods all you need is *SDL-Windows categorization"
currentBackEnd isSDL�
ifTrue: [SDL_ExtWindow target: self]�
ifFalse: [NoopWindow target: self]
SDLExtendedWindow >> #bordered: aBoolean
<primitive: #primitiveNativeCall module:
#NativeBoostPlugin error: errorCode>
^ self nbCall: #( int SDL_SetWindowBordered ( SDL_Window
* target , SDL_bool aBoolean ) )
Haven't actually used this pattern yet, but at least
to me, it yields a clear distinction between what is common
between backends, and what will only work on some.
SDL is of course a somewhat special case, at it
itself is an abstraction over different backends, and there's
little functionality there that could not be part of a standard
window API...
Cheers,
Henry