Sashmark / Blog

Markdown function contract template: promises before a body

Bobby Huang ·

A function contract describes allowed behavior before a function has a body. Its parts are a title, purpose sentence, plain signature, accepted inputs, preconditions, postconditions, unchanged data and a response to unmet preconditions. An invented due-date helper supplies the details in the fenced example.

Key takeaways

  • The title placeholder and purpose sentence identify a single function.
  • A plain signature names the input and possible return values using language-neutral wording.
  • Accepted inputs include an empty list; caller obligations belong under Preconditions.
  • Return promises distinguish a due value, no-due and invalid-input.
  • Each promise names a condition a reader can judge from the described input and return.

A Markdown function contract template gives one function a boundary before its body exists. The boundary says what may arrive, what the caller owes and what may come back. It also names data that remains untouched and the response required when a caller's obligation is unsatisfied.

The contract is an agreement about behavior. A reader should be able to distinguish an allowed return from one the agreement excludes using the words in the file alone.

Defining the function boundary

The purpose sentence gives the function one job. Its signature names the function, its input and the kinds of value it may return. Here the signature is ordinary text, with no claim to any programming language's notation.

Inputs and preconditions do different jobs. Inputs describes the shape of the supplied data, including an empty collection. Preconditions narrows that shape to the values the caller is obliged to supply. Postconditions states the promised return with those obligations satisfied. Unchanged data defines the boundary around everything the function may read but may not alter.

An .md file can hold this agreement beside other writing for a project. Background on this extension appears in the Markdown file guide.

The function contract template and invented example

In the fictional Doe project, developer Jane Doe writes this agreement. She is specifying an invented helper called earliestDoeDue. Its job is to choose a due value from made-up task notes. Neither the helper nor the notes refer to existing code or work.

Only the title is left unfilled. Each heading below it contains invented details to replace when specifying another function. All date values appear as placeholders. The labels earlier and later express their intended order, without asserting any actual dates.

# [function contract title]

Jane Doe's earliestDoeDue helper returns the earliest due value among task notes for the fictional Doe project.

## Signature

earliestDoeDue(notes) -> due value, no-due, or invalid-input

## Inputs

notes is a list of task notes, each containing text and one due value.
An empty list is accepted.
Invented input: "fold the amber card" due [earlier due date]; "place the blue tile" due [later due date].

## Preconditions

The caller supplies a list, and every note contains text and a due value.
Every due value denotes a whole date in the same date convention.
The due values have an unambiguous chronological order; equal dates are allowed.
Every due value is written without leading or trailing spaces.

## Postconditions

For a nonempty list satisfying the preconditions, the returned due value belongs to an input note and is no later than any other input due value.
Equal earliest dates yield that same due value, with no choice of note promised.
For the invented input, the promised return is [earlier due date].
For an empty list, the return is no-due, which is distinct from a due value.

## Unchanged data

The supplied list keeps its length and order.
Every input note retains its text and due value.
The function changes no data outside its return value.
The function makes none of these changes, even when a precondition is unmet.

## Unmet preconditions

An unmet precondition requires invalid-input, with no due value.
invalid-input is distinct from no-due; an empty accepted list is not a refusal.

The signature names three kinds of return. The empty case has its own meaning, no-due, so absence of notes cannot be confused with refusal. The nonempty case promises a date value drawn from the input. It promises neither a particular note nor a new ordering of the list.

The equal-date sentence removes a possible ambiguity: this helper returns a date, not the note carrying it. Two notes may therefore share the earliest date without requiring a choice between their texts. The unchanged-data section applies to both an accepted call and a refusal.

A fence tagged text keeps the Markdown example together as literal writing. For fence notation, consult Markdown code blocks.

Keeping each promise checkable

Use nouns that identify the data and comparisons that identify the obligation. "No later than any other input due value" gives the reader something specific to compare. "Chooses a suitable date" would leave suitable undefined. The promise about membership matters too: an earlier date absent from the input would violate the contract.

Keep each obligation separate from its consequence. The caller supplies comparable dates; the helper owes the earliest one. An empty collection is accepted expressly. Unmet preconditions have a named response. Those sentences describe obligations and permitted returns before a body exists; they offer no evidence about real code.

Read the return promises alongside the unchanged-data promises. A return could satisfy the date comparison while an altered note violates the agreement. Both conditions belong to the same function boundary.

Naming the function contract file

Use earliest-doe-due-contract.md to identify the helper whose promises the file contains. Another helper needs its own purpose and promises, even within the same Doe project. For names that describe the writing inside, consult Markdown file naming.

Keep the function name consistent between the signature and the prose. A changed purpose calls for revisiting the accepted inputs and promised return together, so the agreement still describes one job.

Where Sashmark fits

A function's promises can live in Markdown that a person reads and revises. For people receiving Markdown written by agents, Sashmark plans to bring reading and editing to a desktop app. That app is in development; a function agreement would be text to read or revise there.

Questions

Whose obligation does each condition describe?
A precondition is an obligation on the caller before the function begins. A postcondition states what the function promises when it returns with those obligations satisfied.
Does an empty list violate this example's preconditions?
No. An empty list is an accepted input, and its promised return is no-due.
What does this contract say about an unmet precondition?
The invented helper returns invalid-input without a due value and leaves the supplied list and its notes unchanged.

What Sashmark plans for v1: Features · Roadmap

View as Markdown