I’ve recently startedwith a new message-based device and I was able to write my own driver.
Now I am in the model layer and I am not sure how general the name of the methods and the code in them should be. I am dealing with a driver for a variable waveplate (LCC25 from thorlabs) which essentially creates a voltage to feed the device. So at the end I am setting a voltage as you would do on a function generator. My question is: should the model for this device be compatible with other devices such as function generators? They definitely have common capabilities but this device is much more restricted.
Please, give some advice on this point.
Is the variable webplate connected to a function generator (or DAQ)?
If not, the best is to generate some basic methods in your class to do what you need, for instance, to set an angle to the device. The idea is to abstract the logic of the device itself. If later you connect that waveplate to a different function generator, for example, you could develop a new model and everything will still be working.
The model should be a layer between the driver and the GUI. Once you know how your experiment looks like, you will know what methods are important for your model. For example, keeping in memory the last value submitted, or a more complex operation such as switching between states, etc.
If the device is simple enough, you won’t see much difference between Model and Controller, still, the extra work pays off in the long run.
In a strict MCV design, the model should only compare data, hence it should only have “getters”. Would you advice to add all setters to the controller? eg:
class DeviceModel(): @property def position(self): return self.readfromdevice('position') class DeviceController(): @position.setter def position(self, val): self.writedevice('position', val))
However, now one cannot do
controller.position += 1
In a simple case like the one you mentioned, a Model would only be a relay for the controller, i.e. it will just re-implement the methods and then the MVC pattern starts loosing the point.
If, however, you want to have a model that is only able to read the position but not to set it, or you want to implement special units or whatever, then the model is a nice way to go. Then, your controller is still general and can be used by anybody in different contexts, but you particular use of the device forbids people to set the position.
In my personal definition of MVC for Lab programs, I try to keep the controllers as close as possible to the specifications, which would effectively mean that the controller is a driver (or a wrapper to a C library, etc.) and which sometimes is in itself its own library. Think about PyPylons, or pyDAQmx, etc. While the model is what you do with your device, it’s a personal decision. In this way you allow anybody to use your controller and the reference is really the manual. While the reference for your model is your own documentation.
To summarize, I wouldn’t say that a Model should only have getters, it should also have setters. In this way, the user (or yourself) only interacts with the model. For instance, you could implement caching, limits stricter than per-specifications, etc.
PS: This definition of MVC is what I preach and what I follow. But it’s not something you will find written about online somewhere else (yet).