python-anti-patterns
Pythonコードに含まれる一般的なアンチパターンを検出・レビューする際に使用するスキルです。実装を確定する前やバグの原因として既知の悪習慣が疑われる場合に、チェックリストとして活用できます。
description の原文を見る
Use this skill when reviewing Python code for common anti-patterns to avoid. Use as a checklist when reviewing code, before finalizing implementations, or when debugging issues that might stem from known bad practices.
SKILL.md 本文
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!
修正: 1つのレイヤーでのみリトライする。インフラストラクチャのリトライ動作を理解する。
ハードコードされた設定
# 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モデル、プロトバッファ)
- 混在したI/Oとビジネスロジックがない
- 裸の
except Exception: passがない - バッチ処理での無視された部分的失敗がない
- 欠落した入力検証がない
- クローズされていないリソースがない(コンテキストマネージャーを使用)
- 非同期コードでのブロッキング呼び出しがない
- すべてのパブリック関数に型ヒントがある
- コレクションに型パラメータがある
- エラーパスがテストされている
- エッジケースがカバーされている
一般的な修正のまとめ
| アンチパターン | 修正 |
|---|---|
| 分散したリトライロジック | 統一されたデコレータ |
| ハードコードされた設定 | 環境変数 + pydantic-settings |
| 露出しているORMモデル | DTO/レスポンススキーマ |
| 混在したI/O + ロジック | リポジトリパターン |
| 裸のexcept | 特定の例外をキャッチ |
| バッチがエラーで停止 | 成功/失敗を含むBatchResultを返す |
| 検証なし | Pydanticで境界での検証 |
| クローズされていないリソース | コンテキストマネージャー |
| 非同期でのブロッキング | 非同期ネイティブライブラリ |
| 欠落している型 | すべてのパブリックAPIに型注釈 |
| 成功パスのみのテスト | エラーとエッジケースをテスト |
ライセンス: MIT(寛容ライセンスのため全文を引用しています) · 原本リポジトリ
詳細情報
- 作者
- wshobson
- リポジトリ
- wshobson/agents
- ライセンス
- MIT
- 最終更新
- 不明
Source: https://github.com/wshobson/agents / ライセンス: MIT
関連スキル
doubt-driven-development
重要な判断はすべて、本番環境への展開前に新しい視点から対抗的レビューを実施します。速度より正確性が重要な場合、不慣れなコードを扱う場合、本番環境・セキュリティに関わるロジック・取り消し不可の操作など影響度が高い場合、または後でバグを修正するよりも今検証する方が効率的な場合に活用してください。
apprun-skills
TypeScriptを使用したAppRunアプリケーションのMVU設計に関する総合的なガイダンスが得られます。コンポーネントパターン、イベントハンドリング、状態管理(非同期ジェネレータを含む)、パラメータと保護機能を備えたルーティング・ナビゲーション、vistestを使用したテストに対応しています。AppRunコンポーネントの設計・レビュー、ルートの配線、状態フローの管理、AppRunテストの作成時に活用してください。
desloppify
コードベースのヘルスチェックと技術負債の追跡ツールです。コード品質、技術負債、デッドコード、大規模ファイル、ゴッドクラス、重複関数、コードスメル、命名規則の問題、インポートサイクル、結合度の問題についてユーザーが質問した場合に使用してください。また、ヘルススコアの確認、次の改善項目の提案、クリーンアップ計画の作成をリクエストされた際にも対応します。29言語に対応しています。
debugging-and-error-recovery
テストが失敗したり、ビルドが壊れたり、動作が期待と異なったり、予期しないエラーが発生したりした場合に、体系的な根本原因デバッグをガイドします。推測ではなく、根本原因を見つけて修正するための体系的なアプローチが必要な場合に使用してください。
test-driven-development
テスト駆動開発により実装を進めます。ロジックの実装、バグの修正、動作の変更など、あらゆる場面で活用できます。コードが正常に動作することを証明する必要がある場合、バグ報告を受けた場合、既存機能を修正する予定がある場合に使用してください。
incremental-implementation
変更を段階的に実施します。複数のファイルに影響する機能や変更を実装する場合に使用してください。大量のコードを一度に書こうとしている場合や、タスクが一度では完結できないほど大きい場合に活用します。