Wrapper related classes and interfaces #2489
drdanz
started this conversation in
Architecture
Replies: 1 comment
-
|
Beta Was this translation helpful? Give feedback.
0 replies
Sign up for free
to join this conversation on GitHub.
Already have an account?
Sign in to comment
-
I'll just dump some reasoning I've been doing on wrapper related interfaces
The classes related to Wrappers in YARP at the moment are:
yarp::dev::IWrapper
which has 2 functionsvirtual bool attach(PolyDriver*) = 0
virtual bool detach() = 0
yarp::dev::IMultipleWrapper
which has 2 functionsvirtual bool attachAll(const PolyDriverList&) = 0
virtual bool detachAll() = 0
Most devices implement
IMultipleWrapper
. Among these, the ones which can attach only one device are all doing the same thing, i.e. perform a check on the size of thePolyDriverList
, getting thePolyDriver
for the first element, and performing the actual attach on this. I think this is a source of duplicated code that should be avoided.I believe that at some point it might be decided that IWrappers was supposed to be removed, to replace it everywhere with IMultipleWrapper. Nonetheless for some reason it was never deprecated.
My opinion is that most wrappers should implement both unless there is a good reason for not having one:
Anyway, implementing all 4 functions in all the driver does not make too much sense:
attachAll()
which should basically ensure that the list size is one, take the first element, and callattach()
attach()
, which should create aPolyDriverList
, add the device (defining some name), and callingattachAll()
detach
anddetachAll
methods, are basically the same.The
IMultipleWrapper
interface is definitely more versatile, on the other hand, for devices that can attach only one device, callingattachAll()
is more complicated than just callingattach()
.Moreover, the "All" in the name of the methods, is not very significant.
From my point of view, it would make sense to make
IMultipleWrapper
inherit fromIWrapper
, but it would also make sense to do the opposite.Also, another thing that I would like to consider is the
I
in the name, which is something that, in my opinion, should be reserved to interfaces to part of the robot that can be forwarded usingnws/nwc
, but this is not the case here. For examplePolyDriver
,DeviceDriver
, etc. do not have theI
. But on the other hand, theI
seems to be used to represent "pure interfaces", but they are not used almost anywhere.Concluding, I think that it would make sense to have just one interface that is something like this:
yarp::dev::Wrapper
virtual bool attach(yarp::dev::PolyDriver*) = 0
virtual bool attach(const PolyDriverList&) = 0
virtual bool detach() = 0
and then 2 separate interfaces
yarp::dev::MultipleWrapper : public Wrapper
bool attach(PolyDriver*) override
and
yarp::dev::SingleWrapper : public Wrapper
bool attach(const PolyDriverList&) override final
and perhaps also
yarp::dev::[something like MultipleOnly]Wrapper : public MultipleWrapper
bool attach(PolyDriver*) override final { /* print some error */ return false; }
In this way, the intention of who is creating a wrapper can be immediately very clear:
SingleWrapper
and overrideattach(yarp::dev::PolyDriver*)
MultipleWrapper
and overrideattach(const PolyDriverList&)
MultipleOnlyWrapper
and overrideattach(const PolyDriverList&)
. This one could probably be avoided, but being able to do adynamic_cast
is perhaps more efficient and less error prone than checking the result of theattach(PolyDriver*)
call which will not tell you if the attach failed because you are trying to attach a single device to a wrapper that can attach only two or more, or ifOther options could be to split the Wrapper interface in 2 (which is basically what we have now) and perhaps add some
SingleWrapper
andMultipleWrapper
classes that derive fromIWrapper
andIMultipleWrapper
, or to use some template/sfinae magic to remove the function that should not be used, orConcluding, I'm not really sure how to handle this and I'm open to suggestions.
Beta Was this translation helpful? Give feedback.
All reactions