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

Front-end programming with invariants #1473

Open
stefjoosten opened this issue Mar 6, 2024 · 2 comments
Open

Front-end programming with invariants #1473

stefjoosten opened this issue Mar 6, 2024 · 2 comments

Comments

@stefjoosten
Copy link
Contributor

Ampersand is about programming with invariants, aka constraint-based programming. However, Ampersand rules apply to the back end only. As a front-end programmer used to JavaScript, DOMS, endpoint programming, and the like, I would like to extend this programming paradigm to my front-end programming efforts. This idea came up in a discussion with @bramjoosten recently. It calls for a curiosity-driven thought experiment. @Michiel-s can you reflect on this interesting question?

@stefjoosten
Copy link
Contributor Author

Use Case

As a user of a documentation website, I want to bookmark pages to ensure I can find this page sometime later.
As a front-end programmer, I want to solve this problem by minimizing the back-end programming and maximizing the front-end programming because I feel this is a front-end issue. However, there is no way around storing the state of bookmarks in the back-end, so I cannot avoid back-end programming completely. The following Ampersand program stores the state of bookmarks. The interfaces are a prototype of what I really want: a smoothly working front-end application to integrate into pages of my website.

CONTEXT MyScript

PATTERN Bookmarks
RELATION page[Session*Article] [UNI]
MEANING "The page relation contains the article that is currently displayed to the user of this session."
RELATION bookmark[Session] [PROP]
MEANING "The bookmark relation becomes True when the user pushes the bookmark button."
RELATION cache[Article*Account]
MEANING "The cache relation contains the bookmarked articles."
RELATION delBM[Article*Account]
RELATION insBM[Article*Account]
RELATION sessAcct[Session*Account] [UNI,TOT]

ENFORCE insBM >: (page~;bookmark;sessAcct - cache) - insBM
ENFORCE delBM >: (page~;bookmark;sessAcct/\ cache) - delBM
ENFORCE bookmark :< bookmark - page;(insBM \/ delBM);sessAcct~

ENFORCE cache >: insBM - cache
ENFORCE insBM :< insBM - cache
ENFORCE cache :< cache - delBM
ENFORCE delBM :< delBM /\ cache

ENDPATTERN

POPULATION sessAcct[Session*Account] CONTAINS
   [ ("Bram's laptop","Bram")
   , ("S1","Stef")
   ]
POPULATION page[Session*Article] CONTAINS
   [ ("S1","A382")
   ]
POPULATION cache[Article*Account] CONTAINS
   [ ("A382","Bram")
   , ("A51","Bram")
   , ("A51","Stef")
   , ("A819","Bas")
   ]

INTERFACE ShowAll : "_SESSION";I[SESSION] cRud BOX<FORM>
 [ Accounts : V[SESSION*Account] cRud BOX<TABLE>
       [ Account : I                            cRud
       , "Session (sessAcct)" : sessAcct~       CRUD
       , "Bookmarks (cache)" : cache~           cRUd
       ]
 , Sessions : V[SESSION*Session] cRud BOX<TABLE>
       [ Session : I                            CRuD
       , "Account (sessAcct)" : sessAcct        cRud
       , "Page (page)" : page                   CRUD
       ]
 ]

INTERFACE Session : I[Session] cRud BOX<FORM>
   [ "Account (sessAcct)" : sessAcct   cRud BOX
         [ "my bookmarks" : cache~     cRUd
         ]  
   , "Displaying article (page)" : page
   , Bookmark : I cRud BOX<PROPBUTTON>
       [ label : TXT "Bookmark"
       , setprop1 : bookmark           cRUd
       ]
   ]

ENDCONTEXT

@Michiel-s
Copy link
Member

Ampersand is about programming with invariants, aka constraint-based programming. However, Ampersand rules apply to the back end only. As a front-end programmer used to JavaScript, DOMS, endpoint programming, and the like, I would like to extend this programming paradigm to my front-end programming efforts. This idea came up in a discussion with @bramjoosten recently. It calls for a curiosity-driven thought experiment. @Michiel-s can you reflect on this interesting question?

Interessante gedachte. Laat me ook mijn eerste gedachten delen, zonder dat ik daar goed over na heb gedacht.

De invarianten zitten bij ons niet in de frontend en ook niet in de backend.. Het zit puur in de state van de populatie in de database. Rules (waaronder invariants) leiden nagenoeg altijd tot 1 SQL query die afgevuurd kan worden op de database om overtredingen te detecteren.

Bij invarianten in de frontend moet ik denken aan zaken als verplichte velden in formulieren. Dus zeg maar de state van 1 instantie van een interface.
Als de gebruiker nu een veld leeg laat dat gekoppeld is aan een TOT relatie, dan gaat de data eerst vanuit de frontend, via de API, de backend naar de database. Daar detecteren we middels de invarianten dat het verplichte veld ontbreekt en gaat de melding terug naar de frontend.
Terwijl we in de frontend al weten dat het een verplicht veld is en dat de state niet valide is (negeren we even de exec-engine).
Voor simpele invarianten zoals de verplichte velden zetten we al wel een rood lijntje om het veld heen wanneer deze leeg gelaten wordt, maar complexere expressies worden niet ondersteund.
Dat zou een ontwikkel richting kunnen zijn; het kunnen specificeren van invarianten die gescoped zijn op een interface. Uitdaging is dan wel in welke taal we invarianten generen zodat deze in frontend library geevalueerd kunnen worden. SQL gaat daar waarschijnlijk niet werken.

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

No branches or pull requests

2 participants