From 48cd7a549190c52b66c4c927cde26b38331c42b4 Mon Sep 17 00:00:00 2001 From: =?UTF-8?q?Bj=C3=B6rn=20Brandenburg?= <bbb@mpi-sws.org> Date: Wed, 6 Nov 2019 17:39:46 +0100 Subject: [PATCH] document additional guidelines --- doc/guidelines.md | 71 +++++++++++++++++++++++++++++++++++------------ 1 file changed, 54 insertions(+), 17 deletions(-) diff --git a/doc/guidelines.md b/doc/guidelines.md index b07a1756f..a171d52b4 100644 --- a/doc/guidelines.md +++ b/doc/guidelines.md @@ -15,7 +15,7 @@ This project targets Coq *non*-experts. Accordingly, great emphasis is placed on 5. **Keep it simple.** Shy away from advanced Coq techniques. At the very least, the spec and all lemma/theorem claims should be readable and understandable with a basic understanding of Coq (proofs are not expected to be readable). -## Specific Advice +## Readability Advice - Use many, mostly short sections. Sections are a great way to structure code and to guide the reader; they serve the reader by establishing a local scope that is easier to remember. @@ -23,14 +23,6 @@ This project targets Coq *non*-experts. Accordingly, great emphasis is placed on - Make extensive use of the `Hypothesis` feature. Hypotheses are very readable and are accessible even to non-Coq users, especially when paired with self-explanatory names. -- For consistency, start the name of hypotheses with `H_`. - -- Make proofs "step-able." This means preferring `.` over `;` (within reason). This makes it easier for novices to learn from existing proofs. - -- Making proofs as concise as possible is a *non-goal*. We are **not** playing [code golf](https://en.wikipedia.org/wiki/Code_golf). - -- Document the tactics that you use in the [list of tactics](doc/tactics.md). For new users, it can be quite difficult to identify the right tactics to use. This list ist intended to give novices a starting to point in the search for the "right" tools. - - Consider renaming general concepts with `let` bindings to introduce local names that are more meaningful. In many cases, this is also useful to bind necessary context to local names. For example: ``` Let no_deadline_is_missed := @@ -49,28 +41,73 @@ This project targets Coq *non*-experts. Accordingly, great emphasis is placed on - Document the sources of lemmas and theorems in the comments. For example, say something like "Theorem XXX in (Foo & Bar, 2007)", and document at the beginning of the file what "(Foo & Bar, 2007)" refers to. +## Naming Conventions + +1. For consistency, start the name of hypotheses with `H_`. + +- For case a case analysis of `foo`, use `foo_cases` as the lemma name. + +- For a basic lemma that is intended as a rewriting rule to avoid unfolding a definition `foo` directly, use `foo_def` as the lemma name. + +- Consistently name predicates that express that something "is valid" (i.e., satisfies basic assumptions) as `valid_*` or `respects_*`. +Examples: `valid_schedule`, `taskset_respects_sporadic_task_model`. + +- Consistently name sections that define what it means to be valid w.r.t. to some concept `Foo` as `ValidFoo`. +Examples: `ValidSchedule`, `ValidTask`, `ValidJobOfTask`, `ValidJobsOfTask`. + +- Job parameters are always prefixed with `job_`. +Examples: `job_cost`, `job_arrival`, `job_deadline`. + +- Task parameters are always prefixed with `task_`. +Examples: `task_cost`, `task_deadline`. + +- We do not follow ssreflects naming scheme. + + +## Coq Features + +- We use type classes sparingly. Primarily, type classes are used to introduce new job and task parameters. + +- We rely heavily on type inference. Top-level definitions do *not* require type annotations if the semantics are clear from context and Coq can figure out the specific types. + +- We tend to not use a lot of custom syntax/notation. Heavy use of custom syntax reduces readability because readers are forced to remember all local syntax definitions. + +- We rely heavily on ssreflect notation. + + ## Writing Proofs -- Keep proofs short. Aim for just a few lines, and definitely not more than 30-40. Long arguments should be structured into many individual lemmas (in their own section) that correspond to high-level proof steps. Some exceptions may be needed, but such cases should truly remain *exceptional*. +When writing new proofs, please adhere to the following rules. + +### Structure + +1. Keep proofs short. Aim for just a few lines, and definitely not more than 30-40. Long arguments should be structured into many individual lemmas (in their own section) that correspond to high-level proof steps. Some exceptions may be needed, but such cases should truly remain *exceptional*. Note: We employ an automatic proof-length checker that runs as part of continuous integration to enforce this. +- However, making proofs as concise as possible is a *non-goal*. We are **not** playing [code golf](https://en.wikipedia.org/wiki/Code_golf). If a proof is too long, the right answer is usually **not** to maximally compress it; rather, one should identify semantically meaningful steps that can be factored out and documented as local "helper" lemmas. Many small steps are good for readability. + - Make use of the structured sub-proofs feature (i.e., indentation with `{` and `}`, or bulleted sub-proofs with `-`, `+`, `*`) to structure code. -- Generally try to make proofs as robust to (minor) changes in definitions as possible. Longterm maintenance is a major concern. +- Make proofs "step-able." This means preferring `.` over `;` (within reason). This makes it easier for novices to learn from existing proofs. + -- Make use of the `by` syntax to stop the proof script early in case of any changes in assumptions. +### Maintainability -- General principle: Rewrite with equalities, do not rely on definitions. +Generally try to make proofs as robust to (minor) changes in definitions as possible. Longterm maintenance is a major concern. -- Avoid unfolding definitions in anything but “basic facts†files. Main proofs should not unfold low-level definitions, processor models, etc. Rather, they should rely exclusively on basic facts so that we can change representations without breaking high-level proofs. +1. Make use of the `by` tactical to stop the proof script early in case of any changes in assumptions. -- In particular, for case analysis, prefer basic facts that express all possible cases as a disjunction. Do not destruct the actual definitions directly. +- General principle: **Rewrite with equalities, do not unfold definitions.** +Avoid unfolding definitions in anything but “basic facts†files. Main proofs should not unfold low-level definitions, processor models, etc. Rather, they should rely exclusively on basic facts so that we can change representations without breaking high-level proofs. +- In particular, for case analysis, prefer basic facts that express all possible cases as a disjunction. Do not destruct the actual definitions directly. -- Naming suggestion: for case a case analysis of foo, use foo_cases as the lemma name. +- Do not explicitly reference proof terms in type classes (because they might change with the representation). Instead, introduce lemmas that restate the proof term in a general, abstract way that is unlikely to change and rely on those. +Guideline: do not name proof terms in type classes to prevent explicit dependencies. +### Tactics -- Do not explicitly reference proof terms in type classes (because they might change with the representation). Instead, introduce lemmas that restate the proof term in a general, abstract way that is unlikely to change and rely on those. Guideline: do not name proof terms in type classes to prevent explicit dependencies. +- Document the tactics that you use in the [list of tactics](doc/tactics.md). For new users, it can be quite difficult to identify the right tactics to use. This list ist intended to give novices a starting to point in the search for the "right" tools. *To be continued… please feel free to propose new advice and better guidelines.* -- GitLab