Current Practices

This is a living list. Practices graduate off this page when they stop feeling like conscious effort and become second nature. New ones get added as they are adopted and actively applied. This is not a style guide or a set of recommendations, it is a personal accountability list, reflecting where my development habits are right now. These are not the end all be all of best practices, and I know I still have a long way to go. But the habits on this list are ones I have recently picked up and actively implemented, and I genuinely believe they have made me a better programmer. I look forward to making these second nature and finding new ones to add along the way.

Type Annotations in Python

Function arguments and return types are now annotated as specifically as possible throughout my Python projects. Required arguments carry no default, optional arguments do. Return types are annotated as precisely as the situation allows. This single habit has caught more bugs before runtime than almost anything else, because the IDE picks up on type mismatches and flags them visually before the code ever runs.

Design and Scope Before Implementation

New projects start with a planning phase, not a coding phase. Defining an end goal, scoping the feature set, and mapping out how the project will progress before writing a line of code keeps things on track and reduces scope creep. This practice came partly from experience, the self-hosted VTT and CLI Worldbuilding Toolkit started as one mental project until proper feature planning made clear they were two distinct scopes entirely.

Intentional Project Structure and Modular Organization

Files are no longer dumped into the project root. Related functions live together in dedicated files, and those files live in intentional subdirectories. Database queries, settings, menus, and utilities each have a home. This layout pushes naturally toward OOP thinking and makes the codebase easier to navigate, extend, and reason about, both now and after time away from it.

Pseudo-API File Design and Private Function Naming

Each file is treated as a pseudo-API, meaning the first question asked of any function is whether it is meant to be called from outside the file or only used internally. Internal functions get a leading underscore prefix, external ones do not. This is still being applied consistently across all projects, but the habit is deliberate and the intent is clear.

Structured Logging via AppLogging

Setting up Python's logging module from scratch every time is tedious and error-prone, so a personal AppLogging package handles that setup in a streamlined and defaulted way. It gets used in larger projects and captures errors at various severity levels across all meaningful fail points, especially important once multiprocessing enters the picture, where exceptions can otherwise disappear silently across process boundaries.

Automated Formatting and Complexity Reduction

Black handles Python formatting without negotiation, removing formatting decisions from the equation entirely. SonarQube runs in the IDE and flags duplicate code and functions that exceed a reasonable cognitive complexity threshold. Both tools push toward code that is easier to read and easier to maintain without requiring conscious effort on every line.

Credentials in Environment Files

Credentials and sensitive configuration values live in .env files rather than hardcoded JSON or config files. A small habit with meaningful implications for security and portability across environments.