-
Notifications
You must be signed in to change notification settings - Fork 1
Coding Style Guide
Gianluca Zhang edited this page Feb 4, 2025
·
3 revisions
Maintain a clear, modular folder layout:
capy/
├── docs/
├── src/
│ ├── capy_app/
│ │ ├── backend/
│ │ │ ├── db/ # Database models and connection utilities
│ │ │ ├── mods/ # Additional modules for extended functionalities
│ │ │ ├── res/ # Static resources like images, JSON files, etc.
│ │ │ ├── utils/ # Utility/helper functions
│ │ ├── frontend/
│ │ │ ├── cogs/ # Separate modules for bot commands/features
│ │ │ ├── bot.py
│ │ ├── config.py # Configuration constants
│ │ └── main.py # Entry point of the bot
├── tests/ # Unit and integration tests
│ ├── capy_app/
│ │ ├── backend/
│ │ │ ├── db/
│ │ │ ├── mods/
│ │ │ ├── res/
│ │ │ ├── utils/
│ │ ├── frontend/
│ │ │ ├── cogs/
│ │ │ ├── bot.py
│ │ ├── config.py
│ │ └── main.py
├── .env # Environment variables and secrets
├── requirements.txt # Python dependencies
├── requirements_dev.txt # Development dependencies
├── style.md # Coding style guide
├── test.md # Testing script
└── updater.py # Script for updating host
- Use a class-based design for modularity:
- Define a
Cog
for each bot feature (e.g., moderation, profiles). - Separate utility methods by category into individual files for clarity.
- Define a
- Use snake_case for variables and functions:
def get_user_profile(user_id: str) -> dict:
...
- Use PascalCase for class names:
class UserProfile:
...
- Use lowercase_with_underscores for file names (e.g.,
user_profiles.py
).
- Provide concise, meaningful inline comments above complex code:
# Fetch the user profile from the database
user_profile = db.get_user(user_id)
- Write docstrings for all public functions, methods, and classes. Follow the Google style for docstrings:
def fetch_user_data(user_id: str) -> dict:
"""
Fetch user data from the database.
Args:
user_id (str): The unique ID of the user.
Returns:
dict: The user profile data.
"""
- Include a brief description at the top of each file:
"""
This module handles MongoDB connection and operations
for user profiles.
"""
- Prioritize clarity over brevity:
# Good
for user in user_list:
if user.is_active():
active_users.append(user)
# Bad
active_users = [u for u in user_list if u.is_active()]
- Use descriptive collection and field names:
- Collection names: snake_case plural (e.g.,
user_profiles
). - Field names: camelCase (to match MongoDB standards).
- Collection names: snake_case plural (e.g.,
{
"_id": "123456",
"userName": "johndoe",
"profileSettings": {
"theme": "dark",
"notificationsEnabled": true
}
}
- Use Python's
logging
module:- Log at appropriate levels (
DEBUG
,INFO
,WARNING
,ERROR
,CRITICAL
). - Include timestamps and context:
- Log at appropriate levels (
import logging
logging.basicConfig(
level=logging.INFO,
format="%(asctime)s - %(name)s - %(levelname)s - %(message)s"
)
- Use guard clauses to simplify complex conditional logic:
def process_user(user):
if not user.is_active():
return
# Process active user
...
- As compared to:
def process_user(user):
if user.is_active():
# Process active user
...
- Use helper methods to break down complex algorithms into smaller, manageable pieces, especially for methods with many tab scopes:
def complex_algorithm(data):
result = step_one(data)
result = step_two(result)
return step_three(result)
def step_one(data):
# Perform first step
...
def step_two(data):
# Perform second step
...
def step_three(data):
# Perform third step
...
- Catch specific exceptions, log meaningful messages, and use
raise
to propagate errors:
try:
db.connect()
except ConnectionError as e:
logging.error(f"Database connection failed: {e}")
raise
- Example:
def fetch_user_data(user_id: str) -> dict:
try:
user_data = db.get_user(user_id)
if not user_data:
raise ValueError(f"No user found with ID: {user_id}")
return user_data
except Exception as e:
logging.error(f"Error fetching user data: {e}")
raise
- Minimize the use of
from library import a, b, c, d
. Instead, import the entire module and use it with the module name to avoid namespace conflicts:
# Good
import os
import sys
# Bad
from os import path, mkdir, remove
from sys import argv, exit
- Follow the standard import order: standard library imports, third-party imports, and local imports. Separate each group with a blank line:
# Standard library imports
import os
import sys
# Third-party imports
import requests
# Local imports
from .utils import helper_function
- When adding new scripts to a module, ensure that the module's directory contains an
__init__.py
file. This file can be empty or used to initialize the module.