skills/good-function-design/exports/openai/SKILL.md
Write small, readable, testable Python functions with clear names and explicit inputs and outputs.
npx skillsauth add balandongiv/agent-skillbook good-function-designInstall this skill globally with one command. Works with Claude Code, Cursor, and Windsurf.
3 of 9 scanners reported clean
Some scanners were skipped, did not run, or reported a non-clean status. Review each row below.
This skill guides you through writing Python functions that are small, readable, and easy to test. Apply these principles whenever you write a new function, refactor an existing one, or review code for function quality.
A function should do exactly one thing. If you can describe a function with the word "and" — "it validates the input and saves it to the database and sends an email" — it is doing too much. Extract each responsibility into its own named function.
Aim for functions under 20 lines of code. Shorter functions are easier to understand, easier to name accurately, and easier to test. If a function grows beyond 20 lines, ask yourself: can I extract a meaningful sub-step into its own function?
Function names should describe what the function does, using a verb phrase:
calculate_total_price() — not total() or calc()validate_email_address() — not check() or email()fetch_user_by_id() — not get() or user()The name should be precise enough that a reader does not need to read the body to understand what the function does.
All inputs to a function should appear as parameters. A function should not silently read from global state, module-level variables, or instance attributes unless that is the intended design.
Bad:
def calculate_discount():
return PRICE * DISCOUNT_RATE # reading globals silently
Good:
def calculate_discount(price: float, discount_rate: float) -> float:
return price * discount_rate
Explicit parameters make the function's dependencies visible. They make it easy to test the function with different inputs.
Always return a value explicitly with a return statement. Avoid relying on implicit None returns. Use type hints to document what the function returns.
def find_user(user_id: int) -> Optional[User]:
...
return user # or return None
Every public function should have a docstring that explains:
def calculate_discount(price: float, discount_rate: float) -> float:
"""Calculate the discounted price.
Args:
price: The original price in dollars.
discount_rate: The discount as a decimal (e.g., 0.1 for 10%).
Returns:
The price after applying the discount.
"""
return price * (1 - discount_rate)
A pure function always produces the same output for the same input, and has no side effects. Pure functions are the easiest to test — you just call them and check the return value.
Prefer pure functions. When a function must have side effects (writing to a file, sending an email, updating a database), make the side effects explicit and intentional.
Never use mutable objects (lists, dicts) as default parameter values in Python. They are shared across all calls.
Bad:
def append_item(item, collection=[]):
collection.append(item)
return collection
Good:
def append_item(item, collection=None):
if collection is None:
collection = []
collection.append(item)
return collection
When you have a function that needs improvement:
process(), handle(), do_stuff(). These convey nothing. Use specific names.def save(data, overwrite=True) — consider two separate functions instead.None without clear intent. Use Optional[str] and document it.tools
One-sentence description of what this skill does and when to use it.
tools
One-sentence description of what this skill does and when to use it.
documentation
Review per-subject performance to identify likely outliers, distinguish bad data from difficult but valid cases, and document whether subject exclusion is justified before any filtered rerun.
documentation
Review per-subject performance to identify likely outliers, distinguish bad data from difficult but valid cases, and document whether subject exclusion is justified before any filtered rerun.