DiamondLightSource / dodal

Ophyd devices and other utils that could be used across DLS beamlines
Apache License 2.0
2 stars 8 forks source link

Hold state in a class instead of globals #790

Open stan-dot opened 2 months ago

stan-dot commented 2 months ago

It's a maintainability issue, as the state of the whole application, such as blueapi using this library can be subject to hard to predict changes.

OOP takes care to only allow state mutation through setters, at the moment this is quite haphazard.

This change would definitely be a breaking one to the downstream projects, however not too difficult to implement here.

stan-dot commented 2 months ago

example implementation:


from typing import Final, Type, Optional

class DeviceManager:
    DEFAULT_CONNECTION_TIMEOUT: Final[float] = 5.0

    def __init__(self):
        self.active_devices: dict[str, AnyDevice] = {}
        self.beamline_name: str = ""
        self.path_provider: Optional[UpdatingPathProvider] = None

    def set_beamline(self, beamline: str):
        """Set the beamline name."""
        self.beamline_name = beamline

    def clear_devices(self):
        """Clear all active devices."""
        self.active_devices.clear()

    def clear_device(self, name: str):
        """Clear a specific device by name."""
        self.active_devices.pop(name, None)

    def list_active_devices(self) -> list[str]:
        """List the names of all active devices."""
        return list(self.active_devices.keys())

    def active_device_is_same_type(
        self, active_device: AnyDevice, device: Type[AnyDevice]
    ) -> bool:
        """Check if the active device is of the same type as the provided device."""
        return isinstance(active_device, device)

# Usage Example
manager = DeviceManager()
manager.set_beamline("BL1")
manager.clear_devices()

# Add a device (Example)
manager.active_devices['device1'] = AnyDevice()

# Check if a device is the same type
is_same_type = manager.active_device_is_same_type(manager.active_devices['device1'], AnyDevice)