User manual
Not written yet. This chapter is the help of the person who sets the options of an app: what a line of an option shows, and what is done on it. This service has no page of its own: what is described here is the container an app places in its own.
Developer manual
Not written yet. This chapter is for whoever reads or changes the code: how it is organised, what an app has to do to use this service, the events it consumes, and the stylesheets.
Modelling
Problem and scope
Description
An app of SPPAS does not do one thing: it does what it was told to do. What tells it is a handful of values — a language, a threshold, a file of correspondences, a box ticked — and those values have to come from somebody. That somebody is a person, and she has to be shown what there is to set before she can set it.
This is what shows it, and it is nothing else. It is given what an app lets one set, it shows it in a form which can be acted upon, it takes what was set, it refuses what cannot be used, and it hands back what was decided. It runs nothing, and it does not know what a single one of those values means.
That ignorance is the whole point. A threshold is a number to this domain and nothing more; which threshold, of what, and what happens above it, belongs to the app which declared it. It is what lets one interface serve every app of swapp, and whatever is added next, without being read again.
What an option is made of is established and is not redesigned here:
sppasOption carries a key, a type, an un-typed value, a name, a
short text and a long description, and its type is one of six —
bool, int, float, str,
filename, filepath. This document reads that, and
adds nothing to it.
Defining the needs
Problem statement and objectives
Setting the options of an app raises a difficulty which is neither technical nor linguistic: the person who sets them is not the person who wrote the app. She is handed a few values to decide — a threshold, a window, a language, a file of correspondences — named in a few words by somebody who knew what they were for, and she has to decide them before anything runs. What each of them does, what happens above or below, and what was there before she touched it are not hers to know, and today they are not shown to her.
The central problem addressed here is thus:
how to let a person set what an app will do, when she did not write that app — making every value intelligible before it is given, and reversible after.
The difficulty is sharpened by three conditions. The options are declared by the app and not here: one app offers three, another twenty, and an app written by somebody else offers whatever its author chose, and none of them is known in advance. They are typed but not bounded: nothing says that a threshold is a duration, that a duration is in seconds, or which values are absurd. And the same must serve where SPPAS runs on the machine of the person and where it runs on a server, a difference which is invisible until an option asks for a file.
There is material to work with, and it is already written. Every option carries a short text and a long description, both written by whoever declared it. The interface which exists today shows the first and has never shown the second.
That is why this is designed again, and not translated. Turning the wx panel into a web page would carry that silence over with everything else: a list of widgets, one terse label each, no way back to the value an option arrived with, and a dialog which opens on a machine which may not be the right one. What is unsatisfactory there is not the toolkit, and changing the toolkit would settle none of it.
The objectives follow:
- to show, for every option, what it is for — in a few words, and at length for whoever asks — using what its author already wrote;
- to show the value which stands, before anything is touched;
- to give, for each kind of option, the thing which suits it, and to say that a value cannot be used at the moment it is given and not when the app runs;
- to let an option be put back to the value it arrived with, one option or all of them, without anybody having to remember that value;
- to serve an option which takes a file as the others are served, wherever that file stands and wherever SPPAS runs;
- to keep what was set from one time to the next, so that it is not set again;
- to guarantee accessibility, of what is shown and of what is operated.
This runs nothing, does not know what a value means, and does not judge which values make sense together: all three belong to whoever declared the option. It aims at one thing — that setting an option be a decision taken with what it takes to take it, rather than a number typed into a box.
Expressing the needs
The needs below come from two places: what the apps already declare and what the interface which serves them today does with it, and what a person doing the work runs into. None of them is a need of a machine, and none of them says how it is answered.
Deciding with what it takes to decide
A person who sets an option is rarely the person who declared it. The few words which name it were written by somebody who already knew what it was for, and they are read by somebody who does not: window, threshold, shift say nothing of what they measure, in what unit, or what happens on either side of the value. Whoever declared the option wrote more than those few words — a long description is part of what an option carries — and it has never been shown. The need is therefore not to document the tool: it is to put what was already written where the decision is taken. And the value which stands has to be visible before it is touched, because a person who cannot see what she is changing is not changing it, she is replacing it.
Giving a value in the form it has
An option is typed, and the type is not a detail of storage: it says what kind of thing is being decided. A yes or a no is not a word to be spelled, a number is not a string which happens to hold digits, a file is not a path to be copied by hand. The need is that what is offered to act on matches what is being decided, so that a whole class of mistakes cannot be made rather than being caught afterwards.
What cannot be prevented that way has to be said at once. An app runs for minutes on a set of files; a value it cannot use, discovered there, costs those minutes and the person has to start again with no idea which of the twenty values was the wrong one. The need is that a refusal reaches her where she gave the value, and names it.
Coming back to the value an option arrived with
Options are explored. A person who does not know what a threshold does finds out by moving it, and moving it is only reasonable if she can get back. Today she cannot: once the value an option arrived with has been overwritten, it is gone, and nothing in the interface says what it was. The need is that this value remains reachable — for one option, when she has spoilt one; for all of them, when she wants to start from a state she can name.
An option which designates a file
Two of the six kinds of option do not hold a value: they designate a file. An app which maps SAMPA phonemes onto IPA is given a file of correspondences, and that file belongs to the person — it is her alphabet, her corpus, her convention. In the interface which exists, a dialog opens on the machine where that interface runs, which settles the question by making it invisible: the two machines are the same one.
They are not the same one when SPPAS answers from a server. The file is then on a machine which is not the one which will read it, and designating it is not enough. The need is unchanged for the person — to choose her own file, wherever it stands — and it is the need the provision of files answers, locally as well as online. It is named here, and it is answered there.
Setting once, running many times
An app is not run once. Somebody working on a corpus runs the same one on one set of files, then on another, then on a third, with the same options every time. Setting twenty values at each run is not a service rendered, it is an obstacle, and the person who meets it stops using the options at all and lives with the values the options arrived with. The need is that what was set be found again as it was left.
This is a need of the machine of the person and of no other. What is set where SPPAS runs on her own machine is hers to find again; on a server, there is nobody to find it again for, and nothing of hers stays there.
Accessibility
Everything above rests on things being perceived: a label, a description, the value which stands, a refusal, the way back. Contrast, legibility, text alternatives, keyboard and screen-reader operation, and a stable terminology between what is shown and what an option is called are not qualities added to this domain: they are the conditions under which it does anything at all. An option which cannot be read is an option which was not offered.
Two of the needs listed below are not argued here, because they are the act itself and not a difficulty: that a person sets the options of an app, and that the value she gave is the one which counts.
Eliciting the needs
Eliciting the needs means turning them into things this domain names and shows. What follows is not a list of what the code will do: it is what the person is put in front of, and what each of those things is called here.
Concepts manipulated by this domain
- Option
- One thing which can be set. It carries a key, a kind, a value, a label, a description, and the value it was declared with. It is declared by an app and never by this domain.
- Kind
- What sort of thing an option holds, which says what suits it. There are six: a yes or a no, a whole number, a number with decimals, a text, the name of a file, the path of a folder.
- Value
- What the option holds at this moment. It is what is given back, and it is the only thing of an option this domain ever changes.
- Declared value
- The value the option was declared with. It is what « going back » goes back to, and it is never overwritten.
- Label
- The few words which name an option, written by whoever declared it.
- Description
- What that same author wrote at greater length. It exists, and it is what the interface of today never shows.
- Refusal
- What is said of a value which cannot be used, at the moment it is given, and about that value alone.
- Container
- The piece of page an app places in its own, holding the options it declared. This domain has no page: it has this.
One line per option, and three things on it
The need to decide with what it takes to decide is expressed by a line per option carrying three things and always the same three: what it is — the label, and the description for whoever asks for it; what it holds — the value, readable before anything is touched; and what it may hold — the thing which suits its kind, which is what is acted upon.
The order does not change from one option to the next and the three are never merged: a label which is also the control, or a value which is only visible once the control has focus, puts the person back where she was — changing something she cannot read.
What suits each kind
| Kind | What the person is given | What it prevents |
|---|---|---|
| a yes or a no | Something with two states, and both are visible | Spelling a word which means yes |
| a whole number | A field which takes digits, with the bounds when the option has any | A number which is not one |
| a number with decimals | The same, and the separator is not the person's problem | A comma refused as a full stop |
| a text | A field, and nothing more: what a text may hold is the app's business | Nothing, and it says so |
| the name of a file | A way of designating one of her files | Writing a path which is right on another machine |
| the path of a folder | The same, for a folder | The same |
The last two are the ones which are not a matter of typing, and they are where this domain stops: designating a file is asked of the provision of files, which answers it on the machine of the person as well as from a server. What comes back is a file this domain hands on without opening.
The value an option arrived with
An option holds one value, and changing it overwrites what was there. Nothing of what SPPAS holds says what that value was at the start, so the need to come back cannot be answered by looking: there is nothing left to look at.
It is expressed here as the value on arrival: the value every option of a set holds at the moment the set arrives, written down then and never afterwards. Going back is reading it, for one option or for all of them, and it costs nothing.
It is the one thing this domain holds beside what an option already carries, and nothing is asked of the app for it: an app hands over its options, and what they hold when they arrive is what they hold.
What is said when a value cannot be used
A refusal names the option it is about, says what was expected, and appears beside that option. The values which suit their options are taken in all the same: a person who has given nineteen good values and one bad one has given nineteen good values.
What is refused here is what the kind of an option settles — a number which is not one, a value outside the bounds an option states. What a value means, and whether it makes sense beside another, is refused nowhere here: this domain does not know it, and pretending to would make it the place where every app's knowledge accumulates.
Where the options stand when there are many (inferred need)
No person has asked for this, and it does not come from an expressed need: it comes from what the interface of today is. The panel which serves the options scrolls, in both directions, which is the shape a list takes when nobody knows how long it will be. An app which declares twenty options gives twenty lines with nothing to hold on to, and what is at the bottom is what is never read.
It is expressed here as a need which is inferred and stated as such: that the options of one app be given somewhere which does not require the person to hold twenty things in mind at once. Whether that is an order, a grouping, or something else is not decided by this chapter, and what decides it is what the apps actually declare. It is written down so that the day it is decided, it is decided on purpose.
Organising the needs
[010] The options which are shown
- [012] The system shows every option the app declared, and no other option.
[020] What is read of an option
- [021] The system shows the short label of every option.
- [022] The system shows the long description of an option on demand.
- [023] The label and the description shown are the ones which came with the option.
[030] What is shown of an option
- [031] The system shows the value of every option.
- [032] The system shows what it takes to change the value of every option.
[100] Giving a value
- [101] The person can change nothing of an option but its value.
- [102] The system offers a control suited to the kind of the option.
- [103] The system shows the bounds of the options which have bounds.
- [104] The system holds the value the person gave, and no other value.
[200] Refusing a value
- [201] The system refuses a value only where the value does not match the kind of the option or the bounds of the option.
- [202] The system signals every refused value as soon as the set is validated, and says for each one which value is expected.
[300] Going back
- [301] The person can put an option back to the value it arrived with.
- [302] The person can put every option back to the value it arrived with, at once.
[400] An option which designates a file
- [401] The person can choose her own file for an option which takes a file, wherever that file stands.
[500] Finding the options again
- [501] The person finds the values she gave the time before, without giving them again.
[600] What is really used
- [601] The person obtains a result which matches the values she was shown, those she did not change included.
[700] Finding an option
- [701] The person can find one option quickly among those of an app.
[1000] Accessibility
- [1001] The system holds to the WCAG rules.
Scope
This document covers what an app lets one set: how it is obtained, how it is shown, how it is changed, what is refused, and how what was set is handed back.
What is not covered, and belongs to whoever declares an option: what it means, what it is for, what a value does to an app, and which values make sense together. What is not covered, and belongs elsewhere: where a file stands and how it gets there, which is the provision of files; and the running itself, which is the app's.
sppasOption and sppasBaseOption are read and not
modelled. Their functioning is established, and this document names them as it
names a neighbour.
Conceptual level
Data dictionary
Two data, and that is all this domain holds of its own.
- D1. A set of options — what an app hands over at one time, and what is handed back to it at one time.
- D2. A refusal — what is said of a value which does not suit the option it was given for. It exists while that value is being given, and no longer.
sppasOption is not one of them. Its functioning is established, it
is read and its value is changed, and this document adds nothing to it: it is
named here as a neighbour, as the dossier of Convert names the API which reads
and writes annotations.
Conceptual model of communication
Three actors border this domain. One is a person, one is what calls it, and one is a neighbouring domain it calls in turn.
Actors
- A1. The person — reads what an option is for, sees the value it holds, changes that value, puts it back to the value it arrived with, and chooses a file where an option takes one.
- A2. An app — hands over a set of options, and gets that set back with the values.
- A3. The provision of files — the neighbouring domain which lets the person designate a file of hers, wherever SPPAS runs.
Flows
- F1. A2 → domain — a set of options [012].
- F2. domain → A1 — the short label of every option [021].
- F3. domain → A1 — the long description of one option, on demand [022].
- F4. domain → A1 — the value of every option, and what it takes to change that value [031], [032].
- F5. domain → A1 — the bounds of an option which has bounds [103].
- F6. A1 → domain — the values she gave, for the whole set, when she validates them [101].
- F7. domain → A1 — one refusal per refused option, naming the option and the value which is expected [202].
- F8. A1 → domain — put one option back to the value it arrived with [301].
- F9. A1 → domain — put every option back to the value it arrived with [302].
- F10. A1 → domain — the request to choose a file, for one option [401].
- F11. domain → A3 — the request for a file of the person.
- F12. A3 → domain — the file she chose.
- F13. domain → A2 — the set of options, with their values [601].
Nothing goes to A2 between F1 and F13. An app hands over its options and hears nothing more until they are handed back: it is not told which value was changed, nor when, nor that one was refused. What it gets is the state at the end, once.
Nothing goes to A3 but a request. This domain asks for a file and receives one; it opens none, reads none, and holds what came back as the value of an option and nothing more.
Two needs of the person are carried by this model and answered elsewhere. The file of [401] is answered by A3, which serves it on the machine of the person as well as from a server. And [501] — finding again the values given the time before — is answered by A2: whether the values of a former setting are restored is that app's decision, it hands over the options carrying the values it wants shown, and F1 carries them. This domain does not know whether a value it is given comes from a setting made yesterday or from a declaration written today, and has no need to.
Conceptual model of data
Three classes. The option is one of them without being modelled: it is an object of SPPAS, its functioning is established, and what is held here is its identity inside a set and the value it had on arrival.
The classes of entities
| Class | Properties | What it is |
|---|---|---|
| OPTION SET | # set | What an app hands over at one time, and what is handed back to it at one time (D1) |
| OPTION | # set, # option, value on arrival | One option of a set. What it holds now is its own and belongs to SPPAS; what is held here is the value it had when it arrived |
| REFUSAL | # set, # option, what is expected | What is said of a value which does not suit the option it was given for (D2) |
The relations
| No. | Verb | Leg 1 | Leg 2 |
|---|---|---|---|
| R1 | belongs to | OPTION (1,1) | OPTION SET (1,n) |
| R2 | concerns | REFUSAL (1,1) | OPTION (0,1) |
R1 is an aggregation: an option is named by its key inside its set, and two
apps name an option language without naming the same option. It is
also what identifies an option here — its key inside its set.
R2 reads (0,1) on the side of the option: an option carries one refusal or none, the one of the last validation. A value which is taken in leaves no refusal behind, and a validation which refuses nothing leaves none at all.
The value on arrival is the one thing this domain adds to an option of SPPAS. It is what going back goes back to, and without it nothing could. It is written when the set arrives and never afterwards.
Computed, and never held
- The value an option holds now, which is on the option itself and belongs to SPPAS.
- That a value was changed, which is the value now against the value on arrival.
- What is handed back to an app, which is the set itself.
What is not modelled, and why
- The option itself — its kind, its label, its description, its value. All four are established, read where they are written, and nothing here adds to them.
- What an option means, and what two values are together: the app's, and refused nowhere here.
- The file an option designates, which is the provision of files', and of which this domain holds what came back and nothing else.
Conceptual model of treatments
Eight treatments, and they are all this domain does. Every one of them is triggered by one event, and none of them waits for a second: a set arrives, a person acts on it, an app asks for it back.
The events
| No. | Event | Kind | Comes from |
|---|---|---|---|
| E1 | An app hands over a set of options | external | F1 |
| E2 | The person asks what an option is for | external | The person (A1) |
| E3 | The person validates the values she gave | external | F6 |
| E4 | The person asks to put one option back | external | F8 |
| E5 | The person asks to put every option back | external | F9 |
| E6 | The person asks to choose a file for an option | external | F10 |
| E7 | A file comes back | external | F12 |
| E8 | An app asks for its set back | external | An app (A2) |
T01 — Take in a set of options
Purpose: that a set of options is ready to be acted upon, and that what every option of it holds is written down before anything changes.
| What | Says |
|---|---|
| Synchronisation | E1 |
| Actions | Write the value on arrival of every option of the set |
| Result | The label of every option (F2). Always |
| Result | The value of every option, and what it takes to change that value (F4). Always |
| Result | The bounds of the options which have bounds (F5). Always |
The value on arrival is written here and nowhere else. An option which arrives twice in two sets is two options, each with its own.
T02 — Say what an option is for
| What | Says |
|---|---|
| Synchronisation | E2 |
| Actions | Give the long description of that option |
| Result | The description (F3). Always |
It reads no value and changes nothing.
T03 — Take in the values
Purpose: that the values a person gave become the values of the options, and that she is told which of them could not.
| What | Says |
|---|---|
| Synchronisation | E3 |
| Actions | For every value given: verify it against the kind of its option and against the bounds of that option; set it on the option |
| Result | The option holds that value (F4). For every value which suits the kind and the bounds |
| Result | A refusal naming the option and the value which is expected (F7). For every other value — and that option keeps the value it held |
The values are judged one by one and taken in one by one. A set is not accepted or refused as a whole: nineteen good values out of twenty are nineteen values taken in, and one refusal.
A refusal erases nothing. An option whose value was refused holds what it held before, and the person loses no more than the value she has just given.
T04 — Put one option back
| What | Says |
|---|---|
| Synchronisation | E4 |
| Actions | Set the value on arrival back on the option; drop the refusal that option carries, if it carries one |
| Result | The option holds its value on arrival (F4). Always |
The refusal goes with the value it was about. Keeping it would leave a reproach standing against a value which no longer exists anywhere.
T05 — Put every option back
| What | Says |
|---|---|
| Synchronisation | E5 |
| Actions | Do what T04 does, for every option of the set |
| Result | Every option holds its value on arrival, and the set carries no refusal (F4). Always |
T06 — Obtain a file for an option
| What | Says |
|---|---|
| Synchronisation | E6 |
| Actions | Ask the provision of files for a file of the person |
| Result | The request (F11). Always |
It opens nothing itself, on any machine.
T07 — Take in the file which came back
| What | Says |
|---|---|
| Synchronisation | E7 |
| Actions | Set what came back as the value of the option it was asked for |
| Result | The option holds it (F4). Always |
Nothing verifies that what comes back suits the option. An option which expects a folder may be given a file, and no treatment here notices: this domain does not open what it is handed. What would notice it, and where, is not settled by this document.
T08 — Hand the set back
| What | Says |
|---|---|
| Synchronisation | E8 |
| Actions | Give back the set, every option holding the value it holds |
| Result | The set with its values (F13). Always |
What is handed back is what is on the screen: the options which were changed and the ones which were not, and no refusal — a value which was refused was never taken in.
Organisational level
Organisational model of treatments
One procedure per treatment, numbered as it is. One table and not two: what differs between SPPAS running on the machine of the person and SPPAS running on a server is not what is done here, and not where it is done.
| PF | What it does | Triggered by | In charge | Where | When | Nature |
|---|---|---|---|---|---|---|
| PF1 (T01) | Takes in a set of options | E1 | the domain | the server | when an app hands its options over | automated |
| PF2 (T02) | Says what an option is for | E2 | the domain | the server | when the person asks | conversational |
| PF3 (T03) | Takes in the values of a set | E3 | the domain | the server | when the person validates what she gave | conversational |
| PF4 (T04) | Puts one option back | E4 | the domain | the server | when the person asks | conversational |
| PF5 (T05) | Puts every option back | E5 | the domain | the server | when the person asks | conversational |
| PF6 (T06) | Obtains a file for an option | E6 | the provision of files | the server, then the machine of the person | when the person asks | conversational |
| PF7 (T07) | Takes in the file which came back | E7 | the domain | the server | as soon as a file comes back | automated |
| PF8 (T08) | Hands the set back | E8 | the domain | the server | when the app asks | automated |
One column holds one value, and that is the result. Everything happens on the server. What the browser holds is the gesture — the box ticked, the number typed, the button pressed — and the values already given, which it carries from one request to the next. It decides nothing, because it knows nothing of what an option accepts. RO1, RO2
Five procedures out of eight are conversational, and they are a request each. Validating what was given is one request and carries the whole set; asking for a description is another, and so is putting an option back. That is what makes [202] hold: the refusals come back on the request which carried the values, beside the options they are about.
PF6 is the one procedure this domain does not perform. It appears in the table so that the request it makes to a neighbour is written down, and so that the one moment something happens outside the server is visible.
Rules of organisation
- RO1 — The values already given are carried from one request to the next by the page, and nothing of a set is held on the server between two requests.
- RO2 — A value is verified where it is taken in, on the server. The browser holds no knowledge of what an option accepts, and refuses nothing of its own.
- RO3 — Every request carries the whole set: the option which is being acted upon, and the values of all the others.
- RO4 — The two contexts of execution are one organisation. Nothing here is done in one and not in the other.
- RO5 — This domain has no page of its own. What it produces is a piece of page an app places in its own, and where that piece stands belongs to that app.
- RO6 — A set of options exists for the time an app is being set up, and this domain keeps none of it afterwards.
RO1 is what the neighbouring dossiers already hold to, and it is what lets one implementation serve a context which knows the person and one which does not. It is also what T08 rests on: an app asking for its options back is answered from what the page transmitted, and from nothing else.
Logical level
The tables
Each class of entities becomes a table, and its identifier becomes its key. Three tables, and one of them holds a key and nothing else.
| Table | Columns | Comes from |
|---|---|---|
| OPTION SET | set | The class OPTION SET |
| OPTION | set, option, value on arrival | The class OPTION, and R1 |
| REFUSAL | set, option, what is expected | The class REFUSAL, and R2 |
R1 is an aggregation: the aggregated table takes the key of the aggregating
one, so an option carries the name of its set, and the two together tell one
option from another. Two sets carry an option called language
without carrying the same option.
The key of a refusal is the key of the option it is about. R2 reads (0,1) on the side of the option, and a key says it better than a rule would: an option carries one refusal or none, and a second value given for it takes the place of the first.
OPTION SET is a key and nothing else. The table exists so that the others may name it; what a set is made of is the options which carry its key.
Not in the tables, and belonging to SPPAS: the kind of an option, its label, its description, and the value it holds. All four are read where they are written, and this document adds nothing to them.
Not in the tables, and computed: whether the value an option holds differs from the value it arrived with.
Physical level
Where each table stands
Here the machines are named, and not before. There is no database, no file and no disk: the three tables stand in what the page transmits, and nowhere else.
| Table | Where it stands | Between two requests | What the person sees |
|---|---|---|---|
| OPTION SET | What the page transmits | Nothing: it is rebuilt at every request | The options of the app she is setting up |
| OPTION | The same, the value on arrival travelling with the rest | Nothing | One line, with what she may act on |
| REFUSAL | Made when a value is taken in, and sent back with the answer | Nothing | What was expected, where she gave the value |
This is the one domain of the four which holds nothing anywhere. It has no place of its own, no lifetime to manage and nothing to sweep: a set exists while an app is being set up, and the last request is the end of it. RO6
What comes back from the page is what the page was given, and nothing here can tell otherwise. The value on arrival travels to the browser and comes back with every request; a page which sent back another one would be putting an option back to a value it never arrived with. What that costs is bounded: a person can only do it to the options she is setting herself, and what an app receives it would have accepted from a keyboard. It is written down rather than guarded against.
Operational model of treatments
The organisational level said by what and when; this says in what tasks. One request is one unit: the set is rebuilt from what the page transmitted, the one thing which was asked is done, and what is to be shown is sent back.
| PF | The tasks, in order | What cannot be half done |
|---|---|---|
| PF1 | Read the options an app hands over; write the value on arrival of each of them; build what is to be shown | Nothing |
| PF2 | Rebuild; give the description of one option | Nothing |
| PF3 | Rebuild; then, for every value given: verify it against the kind and against the bounds, and set it on its option or make the refusal | Nothing |
| PF4, PF5 | Rebuild; set the value on arrival back on one option or on all of them; drop the refusals of the options put back | Nothing |
| PF6 | Rebuild; ask the provision of files, saying which option the file is for | Nothing |
| PF7 | Rebuild; set what came back on the option it was asked for | Nothing |
| PF8 | Rebuild; give the set back to the app | Nothing |
The last column holds one word, and it is the consequence of holding nothing. There is no transaction here, no rollback and no recovery, because there is nothing which could be half written: a request which dies leaves the page as it was, and the next request starts from what the page still holds.
Two requests never meet. Two persons setting up two apps carry two sets, each in its own page, and neither is anywhere the other could reach. No lock is needed, and none is taken.
PF6 and PF7 are two requests with nothing held between them. What ties them is carried by the page and by what the provision of files gives back: which option the file was asked for. A file which comes back for an option nobody asked about is a file which is not taken in.
Where the code goes
In sppas/ui/swapp/services/options/: in the family folder of the
services, beside the provision of files, because it is a service and not an
app. One module per kind of knowledge.
| Module | What it does | Procedure |
|---|---|---|
| acceptance | Says whether a value suits the kind of an option and its bounds, and what was expected when it does not. Reads nothing, writes nothing | What PF3 asks of it |
| set | Rebuilds a set from what the page transmitted, holds the value every option arrived with, sets values, puts options back, and gives the set to an app | PF1, PF3, PF4, PF5, PF7, PF8 |
| presentation | Builds the piece of page an app places in its own: one line per option, and what the person acts on | PF2, and the view of every other |
What each one promises, which is the reason for the cutting:
- Acceptance is given a kind, bounds and a value, and answers. It knows no option, no set and no page, which is what lets every rule of what is accepted be tested with nothing installed.
- The set module is the only one which knows what the page transmits and how a set is rebuilt from it. The day that changes, it is the only one to be read again.
- Presentation decides nothing: what it shows was decided before it was called, and the texts it shows are the ones the options carry.
No module here knows what an option means, what a value does, or what an app will run. There is nowhere for that knowledge to be held, which is the ignorance of the first chapter written as a cut.
The request for a file is made to the provision of files and to nothing else. It is the only tie of this domain to a neighbour, and the set module carries it: what comes back is a value like any other.
Implementation model: MVC
The model holds the set, the value every option arrived with and the rules of what a value may be, and it exposes neither the objects of SPPAS nor the provision of files to the rest of the domain. The controller is called once per request, reads the task the app dispatched, and holds nothing afterwards. The view renders and collects, and takes no decision. Three components, three class diagrams.
What answers is not a response of this domain. An app is reached by a URL and answers with a page; this domain is reached by the app which placed its container in that page. There is therefore no recipe to bake a tree here, and one class stands where an app would have one: the manager, which an app holds.
UML
The classes of the model
/ marks what is derived and held by nobody. What the operations
promise is the chapter on the contracts.
| Class | From | Attributes | Operations |
|---|---|---|---|
OptionSet | OPTION SET, OPTION; module set | options, values on arrival, /changed | rebuild(data), value_on_arrival_of(key), set_value(key, value), put_back(key), put_all_back(), refusals(), for_app() |
OptionRefusal | REFUSAL | option, expected | — |
ValueAcceptance | module acceptance | — | accepts(option, value), what_is_expected(option) |
FileForOption | module set | — | ask_for(option), take_in(option, file) |
OPTION SET and OPTION are one class and not two: an option of a set has no
existence outside that set. OptionSet is the only class which
touches an sppasOption, and FileForOption the only
tie of this domain to a neighbour.
An option is an sppasOption, and nothing here is written for
one. Its key, its kind, its value, its name and the text it carries are held
by that object, which this domain holds, reads and sets. A class of this domain
carrying the same thing under another name would be a second truth.
OptionSet.set_value() sets and does not judge: whether a value may
be set is ValueAcceptance's answer, and the controller asks it
first. A class which decided what it may hold would hold the rules as well as
the data, and the rules would then be in two places.
OptionSet.for_app() gives back the options, every one of them
holding the value it holds. It gives back no refusal and no value on arrival:
a value which was refused was never set, and what an option arrived with is
this domain's own business.
What is tied to what
| Tie | Legs | What it is |
|---|---|---|
| holds | OptionSet 1 — 0..n OptionRefusal | A composition: a refusal exists only inside the set whose option it is about |
| uses | OptionSet → sppasOption | A dependency, and the only tie of this domain to the objects of SPPAS |
| uses | FileForOption → the provision of files | A dependency, and the only tie of this domain to a neighbour |
| none | ValueAcceptance | Tied to nothing at all: it answers on a kind, bounds and a value handed to it |
In yUML
To be read at yuml.me, class diagram.
[OptionSet|options;values on arrival;/changed|rebuild();value_on_arrival_of();set_value();put_back();put_all_back();refusals();for_app()]++1-0..*>[OptionRefusal|option;expected]
[OptionSet]-.->[sppasOption]
[ValueAcceptance|accepts();what_is_expected()]
[FileForOption|ask_for();take_in()]
The classes of the view
| Class | Operations | What it shows |
|---|---|---|
OptionsView | populate_tree_content(record) | The container: one line per option, carrying its label, its value, what it takes to change that value, the bounds when there are any, and the refusal when there is one |
A view builds a tree and does nothing else: it decides nothing, refuses nothing, and reaches neither a disk nor a neighbour. What it shows was decided before it was called, and the texts it shows are the ones the options carry. There is one part and not several: what this domain shows is one container, and the page it stands in belongs to the app which placed it.
What is tied to what
| Tie | Legs | What it is |
|---|---|---|
| uses | OptionsView → OptionsRecord | A dependency: it is given it and builds from it |
In yUML
[OptionsView|populate_tree_content()]-.->[OptionsRecord]
The classes of the controller
| Class | Attributes | Operations |
|---|---|---|
OptionsController | record | handle(data), populate_view() |
OptionsRecord | task, set, to_be_shown | serialize(), parse(data) |
| A record comes from no table: it is what one request holds, it serialises itself for transport and parses itself back, and it is held by nobody between two requests | ||
OptionsManager | — | container(), consumes(events), options_for_app() |
OptionsManager is what an app holds, and the only object of this
domain it holds. Where an application of swapp is reached by a URL and answers
with a page, this domain is reached by the app which placed its container: what
answers is not a response of its own but the app's, and this class is where that
difference stands.
What is tied to what
| Tie | Legs | What it is |
|---|---|---|
| holds | OptionsManager 1 — 1 OptionsView, 1 OptionsController | A composition: it builds them, and they go when it goes |
| holds | OptionsController 1 — 1 OptionsRecord | A composition: one record per request, made by the controller and kept by nobody |
| holds | OptionsRecord 1 — 1 OptionSet | A composition: the set lives inside what one request carries |
| uses | OptionsController → ValueAcceptance | A dependency: it asks before it sets |
| uses | OptionsController → FileForOption | A dependency: it asks for a file and takes back what comes |
| uses | OptionsController → OptionsView | A dependency: it hands over what to build from |
In yUML
[OptionsManager|container();consumes();options_for_app()]++1-1>[OptionsController|record|handle();populate_view()]
[OptionsManager]++1-1>[OptionsView]
[OptionsController]++1-1>[OptionsRecord|task;set;to_be_shown|serialize();parse()]
[OptionsRecord]++1-1>[OptionSet]
[OptionsController]-.->[ValueAcceptance]
[OptionsController]-.->[FileForOption]
[OptionsController]-.->[OptionsView]
The states
One thing has states here, and it is what the person reads on a line.
| State | When | What is shown |
|---|---|---|
| as it arrived | No value was taken in for that option since the set arrived | The value, and no way back offered |
| changed | A value was taken in, and it differs from the value on arrival | The value, and the way back to what it arrived with |
| refused | A value was given for that option and could not be taken in | The value the option still holds, and what was expected |
An option is in one of the three and never in two. Refused is not a state of the value which was refused — that value is nowhere — it is a state of the option, and it goes when a value is taken in for it or when the option is put back.
The sequence, from the set to the set
- An app hands its options over and asks for a container to place in its page.
- The value every option arrived with is written down, and the container is built: one line per option.
- The person asks what one of them is for, and the description is shown.
- She gives values, and validates. Every value is verified against the kind and the bounds of its option; those which suit are taken in, and the others come back as refusals beside their options.
- She corrects what was refused and validates again, as often as she wants.
- She asks for a file for an option which takes one. The provision of files answers, and what comes back becomes the value of that option.
- She puts one option back, or all of them, and what they arrived with stands again.
- The app asks for its options back, and receives them with the values they hold.
Steps 3 to 7 happen in any order, any number of times, and none of them has to happen at all. What is not in the list is an order imposed by this domain: there is none.
The error policy
| Level | What happens | What is done |
|---|---|---|
| 1 | A value does not suit the kind of its option or its bounds | That value is not taken in, the others are, and what was expected is said beside that option. Nothing is raised: it is an answer |
| 2 | What the page transmits is not a set this domain gave: an option which is not in it, a key which names none | What cannot be matched is dropped, the rest is taken in, and nothing of the machine is said to anybody |
| 3 | The provision of files answers nothing, or answers a failure | The option keeps the value it held, and the person is told that no file was obtained |
| 4 | Whoever runs the machine has to know: an app which hands over something which is not a set of options | Said where he reads it, and the app is answered that its options could not be taken in |
What is raised is caught by whatever answers a request, and by nothing below it. A person is never shown what a machine says to itself.
The contracts
How to read them
pre is what has to be true on the way in, and what the operation does not check; post is what the caller can count on without looking.
What holds everywhere
- Nothing is held between two requests. Every operation is given what it works on, and keeps none of it. RO1
- What is absent gives back an empty thing — no refusal, an empty set, an empty description — and never nothing at all.
- Only
OptionSettouches ansppasOption. No other class of this domain knows that such an object exists. - Only
FileForOptionspeaks to the provision of files. - Nothing here reads what a value means, and nothing opens a file.
- What is raised is caught by whatever answers a request, and no class below it writes a catch.
Class by class
| Operation | Contract |
|---|---|
| Rebuild a set | pre: what a page transmitted, or the options an app handed over. post: one option per option of the set, each holding the value it holds and the value it arrived with. A set rebuilt twice from one transport is the same set |
| Give the value an option arrived with | pre: the key names an option of the set. post: the value written when the set arrived, which nothing since has changed |
| Set a value | pre: the key names an option of the set, and the value was accepted. post: the option holds that value; the value on arrival is untouched; the refusal that option carried, if any, is gone |
| Put an option back | pre: the key names an option of the set. post: the option holds the value it arrived with, and carries no refusal |
| Put every option back | pre: none. post: every option holds the value it arrived with, and the set carries no refusal |
| Give the refusals | pre: none. post: one refusal per option which was given a value it could not hold, at the last validation; empty when there is none |
| Give the set for an app | pre: none. post: the options, every one holding the value it holds. No refusal, and no value on arrival |
It sets and it does not judge: what may be set was answered before. It is also
the only class which knows that an option is an sppasOption, so it
is the only one to be read again the day that object changes.
| Operation | Contract |
|---|---|
| Accept a value | pre: an option and a value. post: accepted when the value suits the kind of that option and stands within its bounds; refused otherwise. It judges nothing else: not what the value means, not what it is worth beside another |
| Say what is expected | pre: an option. post: what a value for that option has to be, said from its kind and its bounds, and said whether or not anything was refused |
It reads no disk, holds no set and knows no page. Every rule of what is accepted is therefore verified with nothing installed, which makes it the first class to be tested and the last to surprise.
| Operation | Contract |
|---|---|
| Ask for a file | pre: an option whose kind takes a file. post: the request is made to the provision of files, carrying which option the file is for. Nothing is opened on any machine |
| Take in the file which came back | pre: a file, and the option it was asked for. post: that file stands as the value of that option. The file is not opened, and what it holds is not read |
| Operation | Contract |
|---|---|
| Serialise | pre: none. post: everything a next request needs in order to rebuild this set, and nothing of the machine |
| Parse | pre: what a page transmitted. post: the set as it was, or an empty set when nothing was transmitted. Parsed twice, it gives the same set |
| Operation | Contract |
|---|---|
| Handle a request | pre: called once for that request, and never twice. post: the record is rebuilt from what was transmitted, the task is read, and one treatment ran. Every value of a validation was judged, and every value which was accepted was set. Nothing is held after the request |
| Populate the view | pre: the request was handled. post: the view has the record; nothing is decided here |
| Operation | Contract |
|---|---|
| Populate the tree | pre: a record. post: one line per option of the set, holding the label of that option, the value it holds, what it takes to change that value, its bounds where it has any, and its refusal where it has one. Nothing which the record does not say, and no text this class wrote |
| Operation | Contract |
|---|---|
| Give the container | pre: an app handed over a set of options. post: a piece of page holding every option of that set and no other, ready to be placed by the app in its own page |
| Consume an event | pre: an event an app did not recognise. post: true and the event is treated, when the event is this domain's; false and nothing is touched, when it is not |
| Give the options for the app | pre: none. post: the options the app handed over, every one holding the value it holds |
Where each requirement is held
| No. | Held by |
|---|---|
| [012] | OptionsManager, which builds the container from the set it was handed and from nothing else |
| [021], [022] | OptionsView, which shows the label always and the description on the task which asks for it |
| [023] | OptionsView, which writes no text of its own |
| [031], [032] | OptionsView, one line per option |
| [101] | OptionSet, which changes the value of an option and nothing else of it |
| [102], [103] | OptionsView, which is given the kind and the bounds by the record |
| [104] | OptionSet.set_value() |
| [201] | ValueAcceptance, which refuses on the kind and the bounds and on nothing else |
| [202] | OptionsController, which judges every value of a validation, and OptionsView, which shows each refusal beside its option |
| [301], [302] | OptionSet.put_back() and put_all_back() |
| [401] | FileForOption, which asks the provision of files |
| [501] | Nobody here. An app hands over its options carrying the values it wants shown, and whether those come from a former setting is that app's decision |
| [601] | OptionSet.for_app(), which gives back every option with the value it holds |
| [701] | OptionsView, which is where the form of the container is decided |
| [1001] | OptionsView, and nothing else of this domain |
[501] is the only requirement of this dossier held nowhere in it, and it is written down so that nobody looks for it here. [401] is held by one class which asks a neighbour, which is another thing.
What is tested, and where
Without anything installed
No disk, no server, no browser, no neighbour. Sixteen tests out of twenty-one run here, which is what the cutting into three modules was for.
| No. | What is checked | What it holds |
|---|---|---|
| TE1 | A value which suits the kind of its option is accepted; one which does not is refused | [201] |
| TE2 | A value inside the bounds of an option is accepted; the bound itself passes, and one step beyond is refused | [201] |
| TE3 | An option without bounds accepts every value of its kind | [201] |
| TE4 | What is expected is said for an option, whether or not anything was refused | [202] |
| TE5 | Nothing is refused on what a value means: two values which contradict each other are both accepted | [201], and what this domain does not judge |
| TE6 | A set rebuilt from what a page transmitted holds the same options, the same values and the same values on arrival | RO1 |
| TE7 | A record serialised and parsed twice gives the same set | RO1 |
| TE8 | An empty transport gives an empty set, and nothing is raised | RO1 |
| TE9 | Setting a value changes the value of the option and leaves the value on arrival untouched | [104] |
| TE10 | Setting a value changes nothing else of the option: not its kind, not its label, not its description | [101] |
| TE11 | Putting one option back gives it the value it arrived with, and leaves the other options as they were | [301] |
| TE12 | Putting every option back gives every option the value it arrived with | [302] |
| TE13 | Putting an option back drops the refusal that option carried | T04 |
| TE14 | A validation where one value out of twenty is refused takes in the nineteen others, and gives one refusal | T03 |
| TE15 | An option whose value was refused holds the value it held before | T03 |
| TE16 | What is given back for an app holds every option with the value it holds, and holds no refusal and no value on arrival | [601] |
TE14 and TE15 are the two which say what a validation is. A set is not accepted or refused as a whole, and a refusal erases nothing: written the other way round, this domain would lose nineteen good values to punish one bad one.
TE5 is written to fail if somebody helps. Two values which make no sense together are both accepted here, because what they mean belongs to the app. The day this test has to be changed, this domain has started to judge.
With a view, and with a neighbour
| No. | What is checked | What it holds |
|---|---|---|
| TE17 | The tree built for a set holds one line per option, carrying the label and the value of that option | [021], [031] |
| TE18 | The tree holds the description of an option when the record says it was asked for, and holds it otherwise nowhere | [022] |
| TE19 | The tree holds no text which the options did not carry | [023] |
| TE20 | The tree holds the refusal of an option beside that option, and none beside the others | [202] |
| TE21 | The request for a file names the option it is for, and what comes back becomes the value of that option and of no other | [401] |
TE21 is the only test which needs the provision of files. What it checks on this side is the tie: which option a file was asked for, and which option gets it. What the neighbour does with the request is tested in the dossier of that neighbour.
What no test covers, and where they stand
- [501] — finding the values of a former setting. It is held nowhere in this domain, so there is nothing here to test.
- What an option means, and whether two values make sense together: the app's, and judged nowhere here.
- What a page transmits when it has been tampered with. The value on arrival which comes back is taken for what it is, and the physical level says why.
- The WCAG rules, which are verified on the page an app builds, and not on a piece of it.
The tests stand where the project puts its own: in tests/swapp/,
which follows the shape of the sources. Sixteen of the twenty-one need nothing
at all.
Annexes
Annex: Extension of the option
One extension is required by this document, and it is required by [103] and by the whole of what refusing a value means.
E1 — The bounds of an option
What it is. A low bound and a high bound, carried by an option whose kind is a number, and written where that option is declared. An option which declares none accepts every value of its kind.
Why it is needed. sppasOption carries a kind and a value,
and nothing which says what values that option accepts. The interface which
exists today fills the gap where it stands: the panel of the wx interface
offers every whole number between 0 and 2000, and every decimal between the
same two at a step of one hundredth — a threshold in seconds and a
number of channels are offered the same range, and neither is right. Bounds
written in an interface are bounds which every other interface will have to
write again, differently.
What it costs. Two values on an option, given when it is declared and read when a value is judged. Nothing of what exists changes: an option which declares no bound behaves as every option behaves today.
What it is not. It says what a value may be, never what it means. An option which accepts every number between one and ten says nothing of what three does, and nothing of what three is worth beside the value of another option.
Annex: Mockup of the interface
This annex is not a picture of the container. It is the container — the fragment below is HTML, styled by Whakerexa, rendered here by the same stylesheets that will render it inside the page of an app. What is unreadable here will be unreadable there.
The options are the real ones of the search for IPUs, because their labels are real sentences and a mockup written on short labels proves nothing. It shows one state, after a validation where one value was refused and one option was changed. Interactions are inert; the structure, the labels and the wording are not.
Search for IPUs
What the mockup settles, and what it does not
The label stands alone on its line and the control under it. The labels are sentences, written by whoever declared the option and not by this service: a layout which puts the control beside the label holds for Window and breaks on Duration of the analysis window for the estimation of the RMS values, in seconds. The order is the same on every line, and only the control changes with the kind [032].
A number is a field one steps through when its bounds are declared, and a plain text field when they are not. Arrows increase by something and stop somewhere: with bounds they know where to stop, and the step follows from what was declared — one for a whole number, and the precision of the declared value for a decimal, a thousandth where the option was declared at 0.020. The threshold above declares no bound, because it depends on the recording: it is a field, and what it accepts is said in words.
A yes or a no is a switch with no words on it. Writing YES and NO inside it says twice what its position already says, and in a language which is not necessarily the one of the label.
The long description is a ? at the end of the label, folded. It
is discreet because it is read once and the label is read every time; it is on
the label because that is what it explains. An option whose author wrote no
description has no ? at all, rather than one which opens on
nothing — three of the seven options above have none.
Three buttons and not one. Cancel leaves without changing anything, which is the only way out when a person opened the options to look; put everything back answers [302] and is always there; validate sends what was given. The way back of one option is on that option, and appears only where something was changed [301].
The refusal stands under the field which caused it, says what is expected and what the option still holds — the value on the screen is not the value which counts, and the person has to know which is which. The five other options were taken in.
Two things are shown here and are not settled: how the bounds read for a kind which has none to speak of, and where a chosen file is shown when its name is long. They are interface questions, and they are decided against this markup rather than in the abstract.
Annex: Legal notices
- Author: Brigitte Bigi
- Document License: GNU Free Documentation License (GFDL) 1.3
- Copyright (C) 2026 Brigitte Bigi, CNRS
- Creation Date: 2026-09-17
- Last update: 2026-09-18