Skip to main content

Naming Conventions

Python (Backend)

# Modules/packages: lowercase, underscores
exam_verifier.py # GOOD
examVerifier.py # BAD

# Classes: PascalCase
class ExamVerifier: ... # GOOD
class exam_verifier: ... # BAD

# Functions and methods: snake_case
async def get_exam_by_id(exam_id: int): ... # GOOD
async def getExamById(examId: int): ... # BAD

# Variables: snake_case
exam_attempt = None # GOOD
examAttempt = None # BAD

# Constants: UPPER_SNAKE_CASE
MAX_CONTAINER_LIFETIME = 86400 # GOOD
maxContainerLifetime = 86400 # BAD

# Pydantic models: PascalCase, descriptive suffix
class ExamCreate(BaseModel): ... # Input schema
class ExamResponse(BaseModel): ... # Output schema
class UserUpdate(BaseModel): ...

# SQLAlchemy models: PascalCase (singular)
class Exam(Base): ...
class ExamAttempt(Base): ...

# Boolean fields: is_ or has_ prefix
is_active: bool
is_admin: bool
has_passed: bool

SQL (Database)

-- Tables: plural, snake_case
CREATE TABLE exam_attempts ... -- GOOD
CREATE TABLE ExamAttempt ... -- BAD

-- Columns: snake_case
user_id, created_at, is_active, markdown_file_path

-- Indexes: idx_{table}_{column(s)}
CREATE INDEX idx_exam_attempts_user_id ON exam_attempts(user_id);
CREATE INDEX idx_containers_user_id ON containers(user_id);

-- Foreign keys use ondelete='CASCADE' where children should be removed with parent

-- Migrations: {number}_{description}.py (zero-padded 3 digits)
001_initial_schema.py
009_add_laboratory_system.py
010_add_notifications.py

Vue / JavaScript (Frontend)

// Component files: PascalCase + .vue
ExamAttempt.vue // GOOD
examAttempt.vue // BAD

// View files: PascalCase + .vue (route-level)
AdminDashboard.vue
LessonViewer.vue

// Script refs: camelCase
const examData = ref(null)
const isLoading = ref(false)

// API service functions: verb + noun
async getExams() { ... } // GOOD
async fetchExamList() { ... } // OK

// Event handlers: handle + event
function handleSubmit() { ... } // GOOD
function onClickSubmit() { ... } // BAD

// Template props: kebab-case
<TerminalComponent :container-id="id" /> // GOOD
<TerminalComponent :containerId="id" /> // BAD

// Boolean props: no-value means true
<MyComponent :is-visible="true" />

// Emits: kebab-case
emit('exam-submitted', result)
emit('container-started')

API Routes

# Plural nouns for collections
GET /api/exams
GET /api/exams/{id}

# Verb-noun for actions
POST /api/exams/{id}/start
POST /api/exams/{id}/submit

# Resource nesting is shallow (max 2 levels)
GET /api/laboratories/section/{section_id}/laboratory # OK (legacy)
GET /api/laboratories/{id} # GOOD

# Admin routes grouped under /api/admin/
GET /api/admin/users
POST /api/admin/users
PUT /api/admin/users/{id}/role

Environment Variables

# UPPER_SNAKE_CASE, descriptive
DATABASE_URL=postgresql+asyncpg://...
SECRET_KEY=...
LXD_ENDPOINT=https://10.0.0.3:8443
LXD_SSH_JUMP_HOST=65.109.236.163

# BAD
db_url=...
lxdEndpoint=...

File Layout

ThingConventionExample
Python modulesnake_case.pyexam_verifier.py
Vue viewPascalCase.vueExamAttempt.vue
Vue componentPascalCase.vueTerminalComponent.vue
JS servicecamelCase.jsapi.js
MigrationNNN_description.py010_add_notifications.py
Alembic modelsingular PascalCaseclass Exam(Base)
DB tableplural snake_caseexam_attempts