python-anti-patterns について
python-anti-patternsは、Pythonコードのレビュー向けチェックリストです。インフラ、設計、エラー処理、リソース、型、テストを扱い、例と改善案を使ってマージ前やリファクタリング時に問題を見つける手助けをします。
主な機能
- 01リトライと設定管理の問題を確認
- 02設計とエラー処理のアンチパターンを特定
- 03リソース管理と非同期処理のブロッキングを確認
- 04型ヒントとテストの境界条件を網羅
活用シーン
- 01マージ前にPythonコードをレビューする
- 02不適切な実践に起因する可能性のある問題を調べる
- 03レガシーコードを改修し、チーム規約を整える
- 04Pythonのよくある誤りと修正方法を学ぶ
インストール
コマンドをコピーしてターミナルで実行します。
npx skills add https:/ / github.com/ full-stack-skills/ python-skills --skill python-anti-patternsインストール後、Claude Code で/python-anti-patternsを入力して読み込まれたか確認します。
同梱ファイル
SKILL.md と一緒にインストールされる参考資料やスクリプト。
LICENSE.txtagents/openai.yamlexamples/advanced-usage.mdbasic-usage.mdintegration.md詳細
出典に関する声明:wshobson/agents を基にしたスキル内容です
(MIT License, Copyright (c) 2024 Seth Hobson;ライセンス全文は同じディレクトリ内のLICENSE.txtをご覧ください)。
使用、変更、再配布にあたっては、当該 MIT ライセンスの条項に従い、著作権表示を保持する必要があります。
中国語の説明
このスキルでは、フルスタック開発に関するベストプラクティスとパターンを案内します。
name: python-anti-patterns description: よくあるアンチパターンを避けるために Python コードをレビューするときに、このスキルを使用します。コードレビュー時、実装を仕上げる前、または既知の悪いプラクティスに起因する可能性のある問題をデバッグするときのチェックリストとして使用してください。
Python アンチパターンチェックリスト
Python コードでよく見られる間違いやアンチパターンをまとめた参照用チェックリストです。実装を仕上げる前に確認し、問題を早期に発見してください。
このスキルを使用する場面
- マージ前のコードレビュー
- 原因不明の問題のデバッグ
- Python のベストプラクティスの指導や学習
- チームのコーディング規約の策定
- レガシーコードのリファクタリング
**注:**このスキルでは避けるべきことに焦点を当てています。望ましいパターンやアーキテクチャについては、python-design-patterns スキルを参照してください。
インフラストラクチャのアンチパターン
タイムアウト/リトライロジックの分散
# BAD: Timeout logic duplicated everywhere
def fetch_user(user_id):
try:
return requests.get(url, timeout=30)
except Timeout:
logger.warning("Timeout fetching user")
return None
def fetch_orders(user_id):
try:
return requests.get(url, timeout=30)
except Timeout:
logger.warning("Timeout fetching orders")
return None
**修正方法:**デコレーターまたはクライアントラッパーに集約します。
# GOOD: Centralized retry logic
@retry(stop=stop_after_attempt(3), wait=wait_exponential())
def http_get(url: str) -> Response:
return requests.get(url, timeout=30)
二重リトライ
# BAD: Retrying at multiple layers
@retry(max_attempts=3) # Application retry
def call_service():
return client.request() # Client also has retry configured!
**修正方法:**リトライは単一のレイヤーでのみ行います。インフラストラクチャのリトライ動作を把握してください。
ハードコードされた設定
# BAD: Secrets and config in code
DB_HOST = "prod-db.example.com"
API_KEY = "sk-12345"
def connect():
return psycopg.connect(f"host={DB_HOST}...")
**修正方法:**型付きの設定で環境変数を使用します。
# GOOD
from pydantic_settings import BaseSettings
class Settings(BaseSettings):
db_host: str = Field(alias="DB_HOST")
api_key: str = Field(alias="API_KEY")
settings = Settings()
アーキテクチャのアンチパターン
内部型の公開
# BAD: Leaking ORM model to API
@app.get("/users/{id}")
def get_user(id: str) -> UserModel: # SQLAlchemy model
return db.query(UserModel).get(id)
**修正方法:**DTO/レスポンスモデルを使用します。
# GOOD
@app.get("/users/{id}")
def get_user(id: str) -> UserResponse:
user = db.query(UserModel).get(id)
return UserResponse.from_orm(user)
I/O とビジネスロジックの混在
# BAD: SQL embedded in business logic
def calculate_discount(user_id: str) -> float:
user = db.query("SELECT * FROM users WHERE id = ?", user_id)
orders = db.query("SELECT * FROM orders WHERE user_id = ?", user_id)
# Business logic mixed with data access
if len(orders) > 10:
return 0.15
return 0.0
**修正方法:**リポジトリパターンを使用します。ビジネスロジックは純粋な状態に保ちます。
# GOOD
def calculate_discount(user: User, orders: list[Order]) -> float:
# Pure business logic, easily testable
if len(orders) > 10:
return 0.15
return 0.0
エラー処理のアンチパターン
例外の無差別な処理
# BAD: Swallowing all exceptions
try:
process()
except Exception:
pass # Silent failure - bugs hidden forever
**修正方法:**特定の例外を捕捉し、適切にログ記録または処理します。
# GOOD
try:
process()
except ConnectionError as e:
logger.warning("Connection failed, will retry", error=str(e))
raise
except ValueError as e:
logger.error("Invalid input", error=str(e))
raise BadRequestError(str(e))
部分的な失敗の無視
# BAD: Stops on first error
def process_batch(items):
results = []
for item in items:
result = process(item) # Raises on error - batch aborted
results.append(result)
return results
**修正方法:**成功と失敗の両方を記録します。
# GOOD
def process_batch(items) -> BatchResult:
succeeded = {}
failed = {}
for idx, item in enumerate(items):
try:
succeeded[idx] = process(item)
except Exception as e:
failed[idx] = e
return BatchResult(succeeded, failed)
入力検証の欠如
# BAD: No validation
def create_user(data: dict):
return User(**data) # Crashes deep in code on bad input
**修正方法:**API 境界で早期に検証します。
# GOOD
def create_user(data: dict) -> User:
validated = CreateUserInput.model_validate(data)
return User.from_input(validated)
リソースのアンチパターン
リソースを閉じない
# BAD: File never closed
def read_file(path):
f = open(path)
return f.read() # What if this raises?
**修正方法:**コンテキストマネージャーを使用します。
# GOOD
def read_file(path):
with open(path) as f:
return f.read()
非同期処理内でのブロッキング
# BAD: Blocks the entire event loop
async def fetch_data():
time.sleep(1) # Blocks everything!
response = requests.get(url) # Also blocks!
**修正方法:**非同期処理にネイティブ対応したライブラリを使用します。
# GOOD
async def fetch_data():
await asyncio.sleep(1)
async with httpx.AsyncClient() as client:
response = await client.get(url)
型安全性のアンチパターン
型ヒントの欠如
# BAD: No types
def process(data):
return data["value"] * 2
**修正方法:**すべての公開関数に型注釈を付けます。
# GOOD
def process(data: dict[str, int]) -> int:
return data["value"] * 2
型指定のないコレクション
# BAD: Generic list without type parameter
def get_users() -> list:
...
**修正方法:**型パラメーターを使用します。
# GOOD
def get_users() -> list[User]:
...
テストのアンチパターン
正常系のみのテスト
# BAD: Only tests success case
def test_create_user():
user = service.create_user(valid_data)
assert user.id is not None
**修正方法:**エラー条件とエッジケースをテストします。
# GOOD
def test_create_user_success():
user = service.create_user(valid_data)
assert user.id is not None
def test_create_user_invalid_email():
with pytest.raises(ValueError, match="Invalid email"):
service.create_user(invalid_email_data)
def test_create_user_duplicate_email():
service.create_user(valid_data)
with pytest.raises(ConflictError):
service.create_user(valid_data)
過剰なモック
# BAD: Mocking everything
def test_user_service():
mock_repo = Mock()
mock_cache = Mock()
mock_logger = Mock()
mock_metrics = Mock()
# Test doesn't verify real behavior
**修正方法:**重要な処理経路には統合テストを使用します。モックは外部サービスに限定します。
簡易レビュー用チェックリスト
コードを仕上げる前に、以下を確認します。
- タイムアウト/リトライロジックが分散していない(集約されている)
- 二重リトライがない(アプリケーション+インフラストラクチャ)
- 設定やシークレットがハードコードされていない
- 内部型(ORM モデル、protobuf)が公開されていない
- I/O とビジネスロジックが混在していない
-
except Exception: passのような無差別な例外処理がない - バッチ処理で部分的な失敗が無視されていない
- 入力検証が欠けていない
- リソースが閉じられている(コンテキストマネージャーを使用)
- 非同期コード内にブロッキング呼び出しがない
- すべての公開関数に型ヒントがある
- コレクションに型パラメーターがある
- エラー経路がテストされている
- エッジケースがカバーされている
よくある修正方法のまとめ
| アンチパターン | 修正方法 |
|---|---|
| リトライロジックの分散 | デコレーターに集約 |
| ハードコードされた設定 | 環境変数+pydantic-settings |
| ORM モデルの公開 | DTO/レスポンススキーマ |
| I/O とロジックの混在 | リポジトリパターン |
| 無差別な例外処理 | 特定の例外を捕捉 |
| エラー時にバッチが停止する | 成功と失敗を含む BatchResult を返す |
| 検証がない | Pydantic を使って境界で検証 |
| リソースを閉じない | コンテキストマネージャー |
| 非同期処理内でのブロッキング | 非同期処理にネイティブ対応したライブラリ |
| 型指定の欠如 | すべての公開 API に型注釈を付ける |
| 正常系のみのテスト | エラーとエッジケースをテスト |
能力の範囲
✅ 得意なこと
- フルスタック開発に関するベストプラクティス
- コードアーキテクチャの設計ガイダンス
- パフォーマンス最適化の提案
⚠️ 必要な情報
- 具体的なプロジェクトのコンテキスト
- 技術スタックの情報
❌ 対象外
- 技術以外の分野におけるビジネス上の意思決定
- 具体的なコードの実装(ガイダンスのみを提供)
ワークフロー
Step 1: 需求分析
理解项目需求和技术约束
Step 2: 架构设计
设计系统架构和组件划分
Step 3: 实现指导
提供具体的实现建议和代码模式
Step 4: 代码审查
审查代码质量和最佳实践遵循情况
Step 5: 优化建议
提供性能优化和改进建议
Gotchas
1. 过度设计
避免在简单场景中使用复杂的设计模式
2. 性能忽视
不要忽视性能优化,特别是在生产环境中
3. 安全考虑
始终考虑安全性和数据保护
4. 测试覆盖
确保有足够的测试覆盖,特别是边界情况
5. 文档维护
保持文档与代码同步更新