Naming Conventions
Names show up in three places: the repository, the Python code, and the SiLA interface that clients see. The CDK derives the SiLA identifiers from your Python names, so a naming choice in code becomes part of the public interface.
For the reasoning behind feature boundaries and vendor terminology, see Designing Features.
Project and package names
The Connector Factory derives every name from the display name you enter.
| Name | Cookiecutter variable | Case | Example |
|---|---|---|---|
| Display name | connector_name | Title Case with spaces | Agilent Microplate Centrifuge |
| Project name | project_name | hyphen-case | agilent-microplate-centrifuge |
| Package name | package_name | snake_case | agilent_microplate_centrifuge, imported as unitelabs.agilent_microplate_centrifuge |
- The display name is also the GitLab project title.
- The project name is the repository path and the top-level directory. Don't use underscores in it.
- The package name is the import name. Don't use hyphens in it.
- Don't include
unitelabsin the project or package name. The package is already namespaced asunitelabs.<package_name>. - Don't rename an existing connector without a migration plan. Renaming the display name also changes the derived package name, so the connector is rebuilt under a new import path that customers can confuse with the old one, and their update path breaks.
File and folder names
| Rule | Use | Not |
|---|---|---|
| A feature's folder and module are the snake_case form of its class name | random_number_provider/random_number_provider.py for RandomNumberProvider | rng/provider.py |
| Keep file names short; don't repeat the connector or package name | errors.py, units.py, protocol.py | file_system_errors.py, file_system_protocol.py |
Feature names
Name every feature class as a noun plus a role suffix, following the SiLA 2 standard.
| Suffix | Use for | Example |
|---|---|---|
Controller | A feature with any control capability. It can still expose properties. | TemperatureController controls the device and exposes readings |
Provider | A feature that only provides information or sensor values, with no controls | DeviceInformationProvider |
Service | A feature that doesn't actively operate the device: meta features of the SiLA server itself, and maintenance features such as teaching, calibration, or settings that configure how the server is used | ConnectionConfigurationService, TeachingService, CalibrationService |
| Rule | Use | Not |
|---|---|---|
| Name the actor that does the work, not the artifact it handles | BarcodeReaderController | BarcodeController |
Don't include the word Feature | TemperatureController | TemperatureControllerFeature |
| Don't repeat the connector or package name | FileService | FileSystemFileService |
| Don't abbreviate | LiquidLevelProvider | LLProvider |
Before inventing a new feature name, check the SiLA base feature repository for an existing one. Reusing an established name keeps connectors interoperable.
Endpoint names
The CDK derives each endpoint's SiLA identifier from the Python method name.
| Endpoint type | Convention | Method name | SiLA identifier |
|---|---|---|---|
| Unobservable property | Prefix with get_; the CDK strips it | get_serial_number | SerialNumber |
| Observable property | Prefix with subscribe_; the CDK strips it | subscribe_temperature | Temperature |
| Command | Start with an action verb; nothing is stripped | start_ramp | StartRamp |
The get_ and subscribe_ prefixes only signal intent to someone reading the code. A command's verb is kept, so the verb you choose is part of the public identifier.
| Rule | Use | Not |
|---|---|---|
| Use full words, not abbreviations or acronyms | reset_emergency_stop | reset_estop |
Don't repeat the feature's context (on TemperatureController) | start_ramp, current | start_temperature_ramp, current_temperature |
Don't put a unit in an identifier; use a Unit constraint instead | timeout | timeout_ms |
| Use one name for the file, the class, and the public identifier | door_controller.py, DoorController, DoorController | lid.py, DoorController, LidController |
Acronyms
The derivation only capitalizes the first letter of each word, so get_server_uuid becomes ServerUuid. To keep an acronym uppercase, set name= on the decorator:
@sila.UnobservableCommand(name="Set ID Number")
async def set_id_number(self, id_number: int) -> None:
"""
Set the identification number of the device.
Args:
IdNumber: The new identification number.
"""
This produces the identifier SetIDNumber. Without name=, the identifier is SetIdNumber.
Standard command vocabulary
When the device's operation matches one of these verbs, use it. If an operation is close but not an exact match, still use the standard verb and describe the difference in the docstring rather than inventing a variant.
| Verb | Typical use |
|---|---|
initialize / deinitialize | Bring the device into or out of an operational state |
reset | Return the device to a known state |
standby | Put the device into a low-activity state |
start / stop | Begin or end an action with no natural end point |
home | Move axes to their reference position |
open / close | Doors, lids, and other access points |
extend / retract | Carriers, drawers, and linear actuators |
lock / unlock | Locking mechanisms |
seal | Plate sealing |
decap / recap | Tube capping |
update | Apply a change to an existing setting or resource |
info, status, errors | Report device information, state, or error lists |
Vendor terminology
Rename a vendor-specific term to the closest standard term. A vendor's "drawer", "flap", or "hatch" all become "door" in a UniteLabs connector.
When one mechanism combines two operations, name it after the operation the client cares about. A mechanism that opens a door to present a plate is a PlateCarrier with extend and retract, not a Door with open and close, when presenting the plate is the real intent.
The io/ layer is the exception: there, name commands as the vendor's own documentation does, so the protocol layer stays traceable to the manual. See Project Structure.
Repeated modules
When a device has the same physical module several times, register one parametrized class per instance and inject the index through name=. Put the index before the suffix.
| Use | Not |
|---|---|
Door1Controller | DoorController1 |
Pipette2Service | PipetteService2 |
When the instances are interchangeable positions on one resource, such as slots in a centrifuge, use a single feature with a slot parameter instead. See Model Repeated Modules for both patterns.
Last updated