You signed in with another tab or window. Reload to refresh your session.You signed out in another tab or window. Reload to refresh your session.You switched accounts on another tab or window. Reload to refresh your session.Dismiss alert
This issue is long and contains a bunch of different ideas. It might be better to work on it as multiple separate issues, but for now, we can just use it to start discussion.
We arrived at the current mocking framework for our simulation classes because, in the past, initializing vendor devices in a sim environment led to crashes. However, as discussed in #44, this is no longer the case. Thus, someone should look into whether it would be beneficial to move to a framework where we instead subclass the relevant vendor objects.
Benefits
It would better practice. Mockito is designed for testing; not production. Thus, we would probably see significantly less overhead, among other things.
It would make it more clear how each of the mock classes relate to each of the vendor classes, and how the calling and non-implemented method semantics work.
It could prevent undefined behavior in the case that a non-mocked vendor method is called.
We would be much more tightly coupled to the vendor libraries. At the moment, if a method name/argument changes, the method calls fall-through silently. In this new framework, the build would fail after one of these changes, forcing us to update the method.
Costs
We gain less control over how each class is simulated. We have to accept the existence of whatever simulation backend/inheritance hierarchy is created by the vendors.
The mock classes have to extend a specific vendor class. This means that we can no longer have classes like MockedMotorBase and MockPhoenixController that implement a bunch of methods common to multiple controllers. (Side note: MockPhoenixController should probably be updated to delegate some of its logic to MockedMotorBase.) Instead, the clearest option would probably to have these classes create a MockedMotorBase (or other class) internally, and proxy the method calls, adding a bunch of extra boilerplate (if we go this route, we should probably rename the base classes)
(We might be able to do something like write an annotation processor that essentially does what we use Mockito for now, but at compile time and with our own classes, but that would add back some of the complication that we're trying to move away from with this issue.)
Phoenix creates their own SimDevice objects which could conflict with ours (or at least clutter up the environment).
Implementation note: Phoenix already provides SimCollection objects for many of their devices. For these devices, it might be preferable to instead adopt a model similar to the current implementation of MockedCANCoder. Depending on how much CTRE has implemented (which someone should check), it might prevent the need to handle a bunch of features ourselves.
Furthermore, while Phoenix devices don't exactly conform to the WPILib spec, they're pretty close. If all of their API endpoints are fully situatable (which someone should check), It might be worth trying to contact them to ask if they would bring it up to spec. This would remove the need for us to do any work whatsoever for CTRE devices. In my (very quick) skim, the only things I noticed were
CANcoders have their position set as an output rather than an input. Imo, they should rewrite this to be an input and set it using a SimDevice rather than directly, but given how their API works, I see why they'd do this.
Another potential disadvantage to the subclassing approach is that if any of the classes we want to subclass are final, or any of the methods we need to override are final, the subclassing approach won't work. Moreover, even if that isn't a problem at the time we decide to pursue subclassing, if the vendor later makes such things final, we would likely need to revert to using Mockito.
This issue is long and contains a bunch of different ideas. It might be better to work on it as multiple separate issues, but for now, we can just use it to start discussion.
We arrived at the current mocking framework for our simulation classes because, in the past, initializing vendor devices in a sim environment led to crashes. However, as discussed in #44, this is no longer the case. Thus, someone should look into whether it would be beneficial to move to a framework where we instead subclass the relevant vendor objects.
Benefits
Costs
MockedMotorBase
andMockPhoenixController
that implement a bunch of methods common to multiple controllers. (Side note:MockPhoenixController
should probably be updated to delegate some of its logic toMockedMotorBase
.) Instead, the clearest option would probably to have these classes create aMockedMotorBase
(or other class) internally, and proxy the method calls, adding a bunch of extra boilerplate (if we go this route, we should probably rename the base classes)(We might be able to do something like write an annotation processor that essentially does what we use Mockito for now, but at compile time and with our own classes, but that would add back some of the complication that we're trying to move away from with this issue.)
SimDevice
objects which could conflict with ours (or at least clutter up the environment).Implementation note: Phoenix already provides SimCollection objects for many of their devices. For these devices, it might be preferable to instead adopt a model similar to the current implementation of
MockedCANCoder
. Depending on how much CTRE has implemented (which someone should check), it might prevent the need to handle a bunch of features ourselves.Furthermore, while Phoenix devices don't exactly conform to the WPILib spec, they're pretty close. If all of their API endpoints are fully situatable (which someone should check), It might be worth trying to contact them to ask if they would bring it up to spec. This would remove the need for us to do any work whatsoever for CTRE devices. In my (very quick) skim, the only things I noticed were
CANcoder
s have their position set as an output rather than an input. Imo, they should rewrite this to be an input and set it using aSimDevice
rather than directly, but given how their API works, I see why they'd do this.The text was updated successfully, but these errors were encountered: