Purpose¶
A domain module that defines exactly one class stays easy to locate: the file name is the class name, and there is never a second symbol hiding below the first. This rule bounds the number of top-level class definitions per module to one. Definitions nested inside another class or function are not counted; definitions wrapped in flow control (try/except, if TYPE_CHECKING) still count as top level.
Configuration¶
rules:
- name: one-class-per-domain-module
type: symbol-count
description: Domain modules define a single class
within: src/contexts/{ctx}/domain/**
symbol: class
max: 1
ignore_files: [__init__.py]
Violation Example¶
# src/contexts/orders/domain/entities/order.py
class Order:
def __init__(self, order_id: str) -> None:
self.order_id = order_id
class OrderLine: # second top-level class -> surplus
def __init__(self, sku: str, quantity: int) -> None:
self.sku = sku
self.quantity = quantity
Passing Example¶
# src/contexts/orders/domain/entities/order.py
class Order:
def __init__(self, order_id: str) -> None:
self.order_id = order_id
Output¶
$ psl check
src/contexts/orders/domain/entities/order.py:8
[one-class-per-domain-module] Domain modules define a single class
2 top-level class definitions found, at most 1 allowed
Found 1 violation(s).