xiaohongshu
xiaohongshu
class-design
Python class design conventions for this codebase. Apply when writing or reviewing classes including interfaces, inheritance, composition, and attribute access.
Full skill instructions
Favor composition over inheritance. Use Protocol classes for interfaces and dependency injection for shared behavior.
| Principle | Pattern |
|---|---|
| Interfaces | Protocol classes for duck typing |
| Shared behavior | Dependency injection or mixins |
| Inheritance depth | Maximum 2 levels |
| Framework base classes | OK to inherit (BaseModel, nn.Module) |
| Concrete inheritance | Forbidden—use mixins instead |
| Static methods | Avoid—use module-level functions |
| Internal APIs | Design for extension, not restriction |
| Private attributes | Only to avoid subclass naming conflicts |
| Getters/setters | Use plain attributes instead |
Use Protocol to define interfaces. This enables duck typing with static type checking.
# CORRECT - Protocol defines the interface
from typing import Protocol
class Tokenizer(Protocol):
"""Interface for text tokenization."""
def tokenize(self, text: str) -> list[str]:
"""Split text into tokens."""
...
def detokenize(self, tokens: list[str]) -> str:
"""Join tokens back into text."""
...
class SimpleTokenizer:
"""Whitespace tokenizer implementing Tokenizer protocol."""
def tokenize(self, text: str) -> list[str]:
return text.split()
def detokenize(self, tokens: list[str]) -> str:
return " ".join(tokens)
def process_text(tokenizer: Tokenizer, text: str) -> list[str]:
"""Works with any Tokenizer implementation."""
return tokenizer.tokenize(text.lower())
# INCORRECT - abstract base class forces explicit inheritance
from abc import ABC, abstractmethod
class Tokenizer(ABC):
@abstractmethod
def tokenize(self, text: str) -> list[str]:
pass
class SimpleTokenizer(Tokenizer): # Must explicitly inherit
...
| Use Case | Choice |
|---|---|
| Define interface for type checking | Protocol |
| Duck typing with static analysis | Protocol |
Need isinstance() checks at runtime | ABC with @runtime_checkable |
| Framework requires inheritance | ABC |
Inject dependencies rather than inheriting behavior.
# CORRECT - composition via dependency injection
from dataclasses import dataclass
@dataclass
class DocumentProcessor:
"""Processes documents using injected components."""
tokenizer: Tokenizer
embedder: Embedder
storage: Storage
def process(self, doc: Document) -> ProcessedDocument:
tokens = self.tokenizer.tokenize(doc.content)
embedding = self.embedder.embed(tokens)
self.storage.save(doc.id, embedding)
return ProcessedDocument(doc.id, tokens, embedding)
# Usage - compose with specific implementations
processor = DocumentProcessor(
tokenizer=SimpleTokenizer(),
embedder=OpenAIEmbedder(api_key=settings.api_key),
storage=RedisStorage(url=settings.redis_url),
)
# INCORRECT - inheriting behavior from multiple classes
class DocumentProcessor(TokenizerMixin, EmbedderMixin, StorageMixin):
def process(self, doc: Document) -> ProcessedDocument:
tokens = self.tokenize(doc.content) # Where does this come from?
...
# CORRECT - shallow hierarchy
class BaseHandler:
"""Base handler with common functionality."""
...
class FileHandler(BaseHandler):
"""Handles file operations."""
...
# INCORRECT - too deep (3+ levels)
class BaseHandler:
...
class IOHandler(BaseHandler):
...
class FileHandler(IOHandler): # Third level - forbidden
...
Inherit from framework base classes that provide essential functionality.
# CORRECT - inheriting from framework base classes
from pydantic import BaseModel
from torch import nn
class UserConfig(BaseModel):
"""User configuration with Pydantic validation."""
name: str
max_retries: int = 3
class Encoder(nn.Module):
"""Neural network encoder layer."""
def __init__(self, input_dim: int, output_dim: int) -> None:
super().__init__()
self.linear = nn.Linear(input_dim, output_dim)
def forward(self, x: Tensor) -> Tensor:
return self.linear(x)
Never inherit from concrete (non-abstract, non-framework) classes. Use mixins or composition.
# INCORRECT - inheriting from concrete class
class FileProcessor:
def process(self, path: Path) -> Data:
content = path.read_text()
return self.parse(content)
def parse(self, content: str) -> Data:
...
class JsonProcessor(FileProcessor): # Forbidden - FileProcessor is concrete
def parse(self, content: str) -> Data:
return json.loads(content)
# CORRECT - use composition
class JsonParser:
"""Parses JSON content."""
def parse(self, content: str) -> Data:
return json.loads(content)
@dataclass
class FileProcessor:
"""Processes files using an injected parser."""
parser: Parser
def process(self, path: Path) -> Data:
content = path.read_text()
return self.parser.parse(content)
# Usage
processor = FileProcessor(parser=JsonParser())
Use mixins only when composition isn't practical. Mixins should:
*Mixin suffix)# CORRECT - focused mixin for logging
class LoggingMixin:
"""Adds structured logging to a class."""
@property
def logger(self) -> Logger:
return logging.getLogger(self.__class__.__name__)
def log_operation(self, operation: str, **context: Any) -> None:
self.logger.info(operation, extra=context)
class DataLoader(LoggingMixin):
"""Loads data with logging support."""
def load(self, path: Path) -> Data:
self.log_operation("load_start", path=str(path))
data = self._load_impl(path)
self.log_operation("load_complete", path=str(path), size=len(data))
return data
Use module-level functions instead of @staticmethod.
# INCORRECT - static method
class MathUtils:
@staticmethod
def clamp(value: float, min_val: float, max_val: float) -> float:
return max(min_val, min(value, max_val))
# CORRECT - module-level function
def clamp(value: float, min_val: float, max_val: float) -> float:
"""Clamp value to the range [min_val, max_val]."""
return max(min_val, min(value, max_val))
Why avoid static methods?
Use plain attributes. Add @property only when you need computed values or validation.
# CORRECT - plain attributes
@dataclass
class User:
"""User with plain attributes."""
name: str
email: str
age: int
# CORRECT - property for computed value
class Rectangle:
"""Rectangle with computed area property."""
def __init__(self, width: float, height: float) -> None:
self.width = width
self.height = height
@property
def area(self) -> float:
"""Computed from width and height."""
return self.width * self.height
# INCORRECT - unnecessary getters/setters
class User:
def __init__(self, name: str) -> None:
self._name = name
def get_name(self) -> str:
return self._name
def set_name(self, name: str) -> None:
self._name = name
Need to define an interface?
├── Yes → Use Protocol
└── No → Need shared behavior?
├── Yes → Can inject as dependency?
│ ├── Yes → Use composition (dependency injection)
│ └── No → Use a focused Mixin
└── No → Inheriting from framework base class?
├── Yes → OK (BaseModel, nn.Module, etc.)
└── No → Is it concrete?
├── Yes → Forbidden - refactor to composition
└── No → OK if depth ≤ 2 levels
xiaohongshu
technical spec
product ux expert
database patterns
Conduct multi-agent task orchestration and workflow coordination.
Initialize project with Conductor artifacts (product definition,
Expert in web animations, transitions, and motion design using Framer Motion and CSS
Creates Mermaid and ASCII diagrams for flowcharts, architecture, ERDs, state machines, mindmaps, and more. Use when user mentions diagram, flowchart, mermaid, ASCII diagram, text diagram, terminal diagram, visualize, C4, mindmap, architecture diagram, sequence diagram, ERD, or needs visual docume...
PostgreSQL bindings for H3 hexagonal grid system. Use when working with H3 cells in Postgres, including spatial indexing, geometry/geography integration, and raster analysis.
Context-Driven Development skill for projects using Conductor. Use this skill when you detect a `conductor/` directory in the project, when working on tasks defined in a `plan.md` file, or when the user asks about tracks, specs, or plans. Automatically applies TDD workflow, tracks task completion...
Display project status, active tracks, and next actions
Official Stakpak application containerization standard operating procedure, a step-by-step guidline to properly dockerize applications. This is a rule book curated by the Stakpak Team.
Generate, edit, and beat-sync AI video with leading models in one workspace.
The world's fastest calendar for remote work
Transform Your Design with AI Designer by ImgCreator.ai
Revolutionizing Video Production with AI-Powered Creativity
Extend an image past the frame and let AI fill the new aspect ratio.
Discover your celebrity doppelgänger with StarByFace!
ChainClarity explains 700+ crypto whitepapers in plain English, with layered summaries, comparisons, research tools, alerts, and a $4.99 Pro plan.
Opus.ai: Revolutionize Your Web Experience