Skip to content
New issue

Have a question about this project? Sign up for a free GitHub account to open an issue and contact its maintainers and the community.

By clicking “Sign up for GitHub”, you agree to our terms of service and privacy statement. We’ll occasionally send you account related emails.

Already on GitHub? Sign in to your account

Designs to limit error propagation in our code #132

Open
hiiamboris opened this issue Oct 16, 2022 · 0 comments
Open

Designs to limit error propagation in our code #132

hiiamboris opened this issue Oct 16, 2022 · 0 comments

Comments

@hiiamboris
Copy link

Early error detection often saves us debugging time and provides cleaner error messages. It's always important to know what's the first thing that has gone wrong.

Code we write has a certain structure. Single function body is usually written by a single person in a short period of time and is tested as a whole, but even then it's useful to put assertions into the body when one is not 100% certain in it's logic validity. Aggregates of functions - objects, DSLs, source files, modules, programs, remote endpoints - are more complex and it's much harder to oversee data exchange between them. This is where most bugs creep in, and why all Red functions have type signatures, unlike some quick'n'dirty scripts.

Common junctions on the path of data exchange are:

  1. function arguments as data enters it
  2. function return value as data leaves it: e.g. one may put exit somewhere, forgetting to return a value
  3. exposed (unprotected) object fields (facets): what one can assign without breaking the object
  4. dialectic data as being parsed: it's easy to parse a dialect today, but quite annoying to provide error detection and reporting
  5. remote and inter-process exchange (API endpoints), which may be organized as any of the above, but it's common to use functions interface

If I was to rate their validity checking importance from 0 to 10, I would give [10 4 6 7 10] respectively. Return values are often tested by test suites, and object fields aren't always for tinkering, and dialects are not as widespread to compete in importance.

Checks can be divided by category:

  • A. type validity
  • B. value validity:
    • number/pair/vector range
    • predefined set of valid words
    • object's class as fitness for particular purpose
  • C. relations between various function arguments or object's fields (esp. in API calls)
  • D. syntactic correctness of a DSL rule

We only have 1A implemented, and even 2A serves only for documentation purposes.

What happens if e.g. I assign to a face's facet something it doesn't expect? It either:

  • crashes/hangs/deadlocks (try set view/no-wait [] none)
  • does something unexpected without telling me I made a mistake and invites me to waste time debugging it
  • throws an error, as we may have added adhoc checks here and there when someone complained

This is ultimately a doomed approach to design (as if we were carving a window after building a solid concrete wall), and it only allows us to save time now and better undestand the weak points in our design so we can build better later.

I propose using this REP as a place for thoughts on how to improve language's DbC support in the area of data validity checking.

To be competitive eventually we'll need language or library support for all of this.


What I currently have:

Junction \ Category A. Type B. Value (range, class) C. Relations D. Syntax
0. General-purpose #assert #assert #assert N/A
1. Function arguments included in Red advanced-function (#assert)* N/A
2. Function return (#assert)** (#assert)** N/A N/A
3. Object fields classy-object, typed-object classy-object, typed-object N/A
4. Dialect syntax N/A N/A N/A #expect
5. Remote calls

* One not covered here case is conflicting refinements test, which is currently adhoc too. On compatibility matrices. Implementation must be useful on both R/S and Red levels, so fast.

** #assert covers unit (module) testing, but not runtime return value checks, which are also useful, since tests can only cover a very limited domain.

For class validity (B) checks we'll need REP #102, then object is like any other argument.

Links and my confidence in the design (feedback is welcome):

Design Confidence Comment
#assert 9/10 Copy or not is the only question still nagging at me
advanced-function 5/10 Fresh yet
classy-object 5/10 Fresh yet
typed-object 3/10 Just an early experiment, likely to be unified with classy-object
#expect 2/10 Useful, but need a better idea

Spaces serve as guinea pig for classy-object and advanced-function, but while they are a great fit for the first (being objects open to user's modification), advanced-function is only relevant on occasion, maybe in a few dozen functions, and is less used there than assertions. I expect some more function-oriented code, like geometry, would be a much better test.

Sign up for free to join this conversation on GitHub. Already have an account? Sign in to comment
Labels
None yet
Projects
None yet
Development

No branches or pull requests

1 participant