💾 Archived View for republic.circumlunar.space › users › dbane › lsp_doc › breaking_rules.gmi captured on 2020-10-31 at 01:35:23. Gemini links have been rewritten to link to archived content
-=-=-=-=-=-=-
title: Breaking the Rules: Refining Prototypes Into Products
author: Darren Bane
copyright: 2020 Darren Bane, CC BY-SA
Recommendations for a process to refine prototypes into production-quality code are made.
The conventional wisdom is that prototypes should be discarded once the lessons have been learned, and the final product written again from scratch. In the spirit of [1] I argue that improvements in development tools have invalidated this.
There is a long history of recommending prototyping as a way to construct systems. I would personally recommend [2] and [3].
A closely related are is that of "specification animation", quickly writing an implementation of some subset of a formal specification in for example Z or VDM. Prolog is a common choice for this, but I choose Lisp instead.
However, as stated in the introduction, I differ in arguing that it is possible to *refine* a prototype into a product.
The first step is to construct a prototype, or in modern terminology a "Minimal Viable Product". These recommendations follow on from [2] and [4].
The following is probably the most work that makes sense without earning money.
The programming language chosen is a particular style of Common Lisp. A clean subset of CL is desired, so cleave as
as practical[5]. Reasons for this decision include:
Detailed implementations, libraries, etc. are as follows:
For the prototyping phase, you should *really* limit yourself to the ISLisp subset. If absolutely necessary you can choose some of the libraries mentioned in the "Productisation" section below.
Even though this is a prototype, attention should be paid to basic craftsmanship.
file and man (actually,
) pages[7].
As stated above, `declare` should be used for simple run-time type-checking of public functions. For example, the following:
(defun f (x) (declare (fixnum x)) (the fixnum (+ x 1)))
First, software at the level of the previous section is quite usable. It should be confirmed that further improvement is, in fact, required. If so, I argue that there is a repeatable procedure to improve the quality of a (reasonably well-written) prototype to a releaseable product.
First, ensure that the surrounding infrastructure is in place:
Then, the following code & documentation improvements should be made:
Since we have a working prototype, it may make sense to write the documentation (and contracts, and tests) "bottom-up":
1. Contracts, static analysis
2. Test cases
3. Module interface specs
4. Module guide, uses hierarchy
5. Task hierarchy
6. System requirements
Depend only on GFM, in the same spirit as the software. The use of tools like PP and Pandoc should be minised. PlantUML *should* be used where it can replace ad-hoc text.
Documents should be stored under git in a "doc" subdirectory of the project.
I think it is a good idea to keep the separation between library and UI code when using ltk.
The following can be added as sections to the README:
And a proper software requirements spec should be written filling in any blanks that the man pages leave.
The specification of input and output variables is best left at the level of tables and Basic English again.
This was the subject of [4]. The output artifacts are a module guide an set of module interface specs. However, some of this documentation is better in the source code:
.
(defun f (x) (declare (fixnum x)) (assert (precondition x)) (let ((res (+ x 1))) (assert (postcondition res)) (the fixnum res)))
`lisp-critic` can be used to perform static analysis of the codebase.
ltk is great for local GUIs. However, a product may require HTMX and the platform.sh stack. Note that I prefer HTMX & ReST (following Fielding) to single-page applications (outside the very specific case of drawing on a canvas using ParenScript).
For productisation you may want to add more features.
Although the official ANSI standard is moribund, quasi-standard libaries are recommended on the
, or
. Usage should be limited as follows, in order of preference. The language/library split isn't as clear in CL as in some other languages, but use your judgement.
" from that list
list
The `trivial-` libraries may be *forked* and maintained locally.
For example:
Unit (FiveAM) tests grow in parallel with the module interface specs. Property-based testing would be nice here, but there doesn't seem to be a readily-available library. System tests grow in parallel with the requirements spec. It's ok for system tests to use the same interfaces as the ltk code. All tests should be automated, except possibly for the UI/view layer. Q: These scripts could be generated from a literate test plan? A: yes, probably one of the few places to use "PP".
As much of the testing work should be pushed "back" in the V model to contracts for the functions, following the pattern above.
A method for developing software from an incomplete understanding of the requirements is given. It is hoped that this is more effective than most of what is currently-used.
[1]Kent Beck, Extreme Programming Explained (1999).
[2]David Robertson and Jaume Agustí, Software Blueprints: Lightweight Uses of Logic in Conceptual Modelling, Addison Wesley Longman (1999).
[3]Kent Pitman, Accelerating Hindsight: Lisp as a Vehicle for Rapid Prototyping (1994).
[4]Darren Bane, Design and Documentation of the Kernel of a Set of Tools for Working With Tabular Mathematical Expressions, University of Limerick, Ireland (19 Jul 2008).
[5]Darren Bane, An ISLisp-like subset of ANSI Common Lisp, Ireland (21 Aug 2020).
[7]Kristaps Dzonsons, Practical UNIX Manuals. available:
https://manpages.bsd.lv/toc.html
[accessed 9 Oct 2020].