This page is not created by, affiliated with, or supported by Slack Technologies, Inc.
2022-03-22
Channels
- # announcements (16)
- # babashka (7)
- # babashka-sci-dev (14)
- # beginners (34)
- # calva (80)
- # clj-kondo (23)
- # cljdoc (17)
- # cljs-dev (1)
- # cljsrn (10)
- # clojure (51)
- # clojure-berlin (3)
- # clojure-europe (14)
- # clojure-italy (10)
- # clojure-nl (2)
- # clojure-norway (211)
- # clojure-uk (5)
- # clojurescript (4)
- # cursive (22)
- # datalevin (12)
- # datomic (2)
- # defnpodcast (1)
- # duct (5)
- # emacs (4)
- # events (2)
- # fulcro (3)
- # graalvm (1)
- # interop (3)
- # introduce-yourself (4)
- # java (1)
- # jobs (7)
- # kaocha (38)
- # leiningen (3)
- # lsp (11)
- # malli (4)
- # membrane (5)
- # music (1)
- # off-topic (28)
- # pathom (13)
- # pedestal (3)
- # polylith (4)
- # portal (10)
- # practicalli (1)
- # re-frame (33)
- # reitit (2)
- # remote-jobs (1)
- # sci (6)
- # shadow-cljs (49)
- # sql (4)
- # xtdb (3)
ClojureScript er jo Clojure sin killer app, folkens. Det er ikke noe sted Clojure sin tankegang gjør større løft enn i frontenden. IMHO. 😘
Problemet er jo at det er så veldig mange JS/TS folk/app’er der ute at det er vanskelig å få skvisa inn CLJS
Pluss at frontendutviklerne stort sett er så unge at de ikke skjønner hvor ille de egentlig har det.
Men problemet er litt sånn at når du er i ferd med å dø av thousand paper cuts og noen viser deg de enkelte kuttene, så sier du at jammen, det er jo ikke så ille.
At folk har havnet i uføret å overlate frontenden sin til en gjeng jyplinger rett fra skolebenken som lager et eneste stort virvar med React hooks får de nesten skylde seg selv for 😅
Nå er det jo slik at hvis jeg får velge mellom et virvar av React hooks og litt god gammel miks av JQuery/Backbone/Handlebars så velger jeg nok React hooks.
Stemmer sikkert, men en falsk dikotomi var det også. Fritt fra kontekst, i hvert fall.
Men, liksom, bare noe så vanskelig som byggesystemer. Det er jo en dumpster fire uten like. Noe går feil, ja, ja, får nuke node_modules og kjøre en yarn install og håpe på at det fikser seg selv.
Joda, jeg vet det finnes en vei utenom. Problemet er at en har 20 utviklere som sakte blør ihjel av bitte små kutt og er fornøyd med det.
Nei? Zombiene er jo så flinke til å bite?!
Jeg setter veldig stor pris på ditt og @christian767 sitt bidrag. Om ikke annet så gleder det meg.
Du kan rive ClojureScript ut av de stive, døde fingerne mine
Diskusjonen om typer til side: Bare all tiden man sparer på å løpe etter JS-økosystemet er glatt verdt investeringen.
Så lenge man da klarer å løsrive seg skikkelig. Jeg vet om ClojureScript-prosjekter som fortsatt løper etter React-økosystemet, og da har man bommet litt, etter min mening.
Absolutt
Jeg har lenge tenkt at jeg ikke kan se for meg at jeg kommer til å jobbe i en JavaScript-frontend igjen i overskuelig fremtid, men etter noen sånne diskusjoner så får jeg et lite masochistisk ønske om et 3 måneders opphold i et prosjekt for å se om det er jeg som misforstår og at det egentlig har blitt bra igjen. Men så kommer jeg på at man ikke engang kan bruke paredit i JS, og så roer det seg 😅
Sett på https://github.com/Fuco1/smartparens ? Den skal visst gjera litt paredit-greier for tøysespråk. (Har berre såvidt testa sjølv, så veit ikkje kor bra det funkar.)
Noteres til en eventuell fremtid der jeg må forholde meg til ikke-lisp 🙂
@christian767 vi driver og skriver om gammel js/backbone til TS/RxJS/React. Jeg kan kanskje klare å overbevise sjefen om å hyre deg inn i tre måneder.
“dessverre” er jeg hyret inn for å drive med Clojure/ClojureScript 😢
Men klart, en halvveis, veldig irriterende conf av paredit høres artig ut 😅
Litt meta: Jeg føler at samtalene i kanalen hadde blitt enklere å følge hvis vi ble flinkere til å bruke samtaletråder, typ knappen “Reply in this thread” (snarvei T
på tastaturet) ☺️ Hvis jeg får lov til å legge inn et velment organisatorisk forslag.
Meta fra meg: Slack-tråder er hvor meldinger går for å dø 🙃 Kanskje bare jeg som er vanskelig.
bare å børste støv av de gamle IRC-skillsa hvor man hadde 5-6 samtaler gående samtidig i samme kanal
> Pluss at frontendutviklerne stort sett er så unge at de ikke skjønner hvor ille de egentlig har det. Den eldgamle Figwheel demoen av live utvikling av Angry Birds hjal meg nesten til å overbevise kolleger til å gå for cljs. Man trenger ikke bare utpeke problemer med JS, som ikke fungerer om målgruppa har ikke opplevd/skjønt nok av de. Man kan også vise det som er kult med cljs 🙂
nå har forresten den ultimate Cloure-boken blitt skrevet! https://www.manning.com/books/data-oriented-programming
litt som Simple Made Easy, argumenterer boka for Clojure uten å nevne Clojure i noen større grad
jeg har holdt på sånn helt siden jeg oppdaget Clojure, ikke snakk om at jeg klarer å kose meg på frontend-prosjekt i JS uten Immutable.JS eller mori
på hyggelig vis argumenterer den også for DDP men bruker lite energi på argumentere mot OOP, så jeg vil tro at den er ganske spiselig. Skal gis i julegave til alle utviklere som (i følge meg 100% definitivt uten tvil) trenger den
jeg har snakket varmt om hooks her før. Men jo mere jeg bruker hooks, jo kaldere bli det... Det er mæget vanskelig å få de korrekt. På react-hook-frontenden jeg holder på med nå blir typ data fetchet et sted mellom 1 og 4 ganger avhengig av timing og race conditions. 90% av problemene kommer fra mangelen på god equality og value semantics. Jeg får det ganske greit til å gjøre det riktig (💪), men så har jo jeg 20 års erfaring med frontend-utvikling og. Andre flinke men mindre erfarne folk får det nesten aldri helt riktig
Prøvd react query? Da sier du noe sånt som "sånn kan data hentes", gir det en ID som er unik over appen, så er den litt "lur" med deling av resultater og spørring etter ny data. https://react-query.tanstack.com/ Kanskje litt vel magisk for din smak?
React-folka sier det jo selv, hooks handler mere om å eksponere primitiver som allerede finnes under panseret i React
Jeg fikk inntrykk av at react-hooks på en måte tok over som “snakkis” over tilstandslagre som Redux. Vet ikke om det er slik andre opplevde det sånn :thinking_face: Iallefall gjorde det meg ganske skeptisk i lang tid. Det morsomme er jo at hooks på mange måter bare er en enklere måte å flytte tilstand tilbake inn i komponentene igjen. Så det blir liksom lavere friksjon på å gjøre komponenter mindre funksjonelle 🙈
@U04V5VAUN vi har vel en (eks-)kollega som omtalte hooks som “magic”, og han var derfor ikke interessert i det :rolling_on_the_floor_laughing:
React-teamet har virkelig jobbet hardt de siste fem årene med å fjerne seg fra idéen som virkelig fenget: en effektiv enveis transformering av data til dom.
akkurat hooks er på en måte greit nok, som nevnt så er ikke det noe "ekstra" de har laget som går utover ytelsen osv, har forstått det som at hooks ble sett på som å eksponere det React allerede hadde under panseret. Tror feilen ligger i at hooks har blitt tatt i bruk av React-miljøet som et primitiv som er nyttig og bra nok for GUI-programmering
pluss at en hook særlig, useEffect
, gjør det for lett å gjøre I/O fra gui-komponentene og ikke ha noe state-behandling på toppnivå i det hele tatt. Men det er også et problem som ligger i React-miljøet, ikke React core, vil jeg si
imo så er det jo en nødvendighet å kunne ha små maskiner her og der i treet, av ytelsesgrunner
da det er sagt så får jeg det jo fint til med snabbdom/dumdom, ved å bare rendre til et DOM-element via refs, så...
> imo så er det jo en nødvendighet å kunne ha små maskiner her og der i treet, av ytelsesgrunner Jeg har jobba med frontend på dette viset i faen skjære meg snart 10 år, og kan telle på én hånd hvor mange ganger jeg har måttet til å gjøre noe annet enn top-down av ytelsesårsaker
Og de få gangene jeg har hatt det problemet har det vært helt løselig på utsiden, uten å trå til med tilstand i komponentene
samme her faktisk, er bare i denne CMS-en min jeg har hatt behovet. Siden jeg lager min egen editor ble det litt heftig å rendre hele treet på hvert tastetrykk i et input-felt. Kan vel sies å være en nokså sær case
Jeg har også jobbet med frontend på denne måten i mange herrans år, og unntakene for min del har vært "et UI-element skal følge fingeren din". Da kan man oppleve at det lugger. Det er ikke nødvendig å vri hele frontendarkitekturen din rundt så sjeldne use cases (med mindre du bygger din egen editor 😄 )
Men. Ikke pga ytelse, men pga letthet. Hvordan dealer dere med forms som skal fylles ut. Lagrer dere mellomtilstanden til formen i global state? Det er typisk et sted der jeg bruker lokal state for å fylle opp alle feltene, for så å shippe alt avgårde når brukeren trykker submit
Det har jeg skrevet en bloggpost om 😅 https://www.kodemaker.no/blogg/2020-10-samspill-mellom-generiske-ui-komponenter/
Dersom det skal være dynamiske endringer i skjemaet avhengig av verdiene i feltene, så oppdaterer jeg global state underveis.
gjør tilsvarende i CMS-en, editoren er implementert som om den var et input-felt. Har referanser til dem, og henter ut en value ved behov, oppdaterer ikke noe app-state på onChange (men kan hvis jeg vil)
forms er også der jeg oftest ser forsøk på smarte abstraksjoner gå skeis.... kan være digg helt i starten med en generisk form builder, men så plutselig brakk man halvparten av formene etter en endring i form builderen pga en annen form, og i det hele tatt...
rettelse: jeg lagrer form values onChange, for å alltid ha siste verdi liggende "sentralt", men jeg lagrer den tilstanden et eget sted som ikke automatisk fører til en ny render av hele appen
hva er dette "mellomstates" du snakker om, @U04V5VAUN?
Hvis du slenger dem inn i global storage så kan du lage fin validering osv uten å søle til form-komponenten
Form-komponenten trenger bare å vite hvordan ting skal rendres. Er det en feilmelding så dukker den opp på rett sted. Den trenger ikke å vite hva som fører til hvilke feilmeldinger - det er kontekstuelt.
Poenget her er jo å ha en ensrettet dataflyt. Fra store -> prepare -> render -> dom. Rene funksjonelle transformasjoner hele veien. Langt lettere å følge flyten enn "mange små maskiner"
Interessant. Også fordi det blir en hersens mange actions som vi må (type) definere og lyttere på disse etc osv osv. ser at dette er mye enklere i cljs enn slik vi har endt opp
Hvis du lager spesifikke actions til så får du veldig mange
Vi bruker for det aller meste små generiske actions
Joa, men de holder informasjonen man trenger, i eksemplet til @magnars så var det i form av «login-form/username» Vi ville sikkert hatt en dedikert action for det, ikke ulikt slik man velger å ha gettere/settere i Java.
{:type "email"
:placeholder (tr (:locale state) ::form-email)
:value email
:change [:save-in-store [:reception/login :email]]
:disabled? (= :requesting-otp status)
:autofocus true}
Dette er dataene til epost-feltet i login-skjemaet vårtemail
er her da (get-in state [:reception/login :email])
får den inn en core.async channel elns i tillegg? Aka hvor sender den dataene i :change når eventet trigges?
Det har jeg også skrevet en bloggpost om 😉 https://www.kodemaker.no/blogg/2020-01-enkel-arkitektur/
tldr; dumdom kan ha én global event-listener som dispatcher til event busen, slik at komponentene kan bruke data “som event-listenere”
men dette er en arkitektur vi har brukt i årevis - dumdom sin feature er helt ny - så man trenger ikke verktøytstøtte for å få til dette altså 😅 Selv om det er meget sweet, så klart.
neinei, det er bare krem på kaka
@magnars ble nysgjerrig på detaljene bare, bloggposten din nevner vel ikke hvordan det løses teknisk
Nei, med overlegg, for det er ikke egentlig et teknisk problem, men et designproblem 🙂
Du kan se gist-en av idéen i s02e02 av zclj, når Christian lager en event-bus på 8 linjer kode eller hva det ble. 🙂
når CMS-en får seg navn/logo så må vi få mekka sånn logo-salat på github-siden til dumdom, "projects using dumdom" 💪 Sånn at dumdom kan få masse brukere som bare vil ha det mest populære cljs-biblioteket for rendring
Hvordan håndterer dere store data volumer? Må en liste komponent re-rendres hvis en greie i listen endrer?
Lista må re-rendres, ja
Det er jo en diff-algoritme som lager et minste sett av DOM-operasjoner, "old school React"-style.
nøyaktig ingen har vel helt løst det med å smooth rendre tusenvis av elementer i en liste. Ikke engang de som ha fått det til, de gjør det jo ved å ikke rendre alt i lista
Er ikke så ofte jeg har trengt å rendre virkelig store datamengder
Det jeg liker litt med reagent er at det er lett å få det til slik at bare en ene re-rendres
Det er lett å få til, men er det nødvendig?
Det jeg misliker med reagent er at det er lett å gi slipp på enveis dataflyt 😅
Mennesker kan jo normalt sett ikke forholde seg til tusenvis av elementer i en liste, så her tenker jeg at løsningen vil være å bygge UI-er som mennesker kan bruke - da gjerne ved å vise et utvalg av lista av gangen.
er man pokka nødt så er det relativt håndterlig å løse dette uten reagent og. Rendre lista, en key per element, bruk en ref, ta vare på key + ref, rendre dem én og én ved behov
Det er sikkert en god løsning for de fleste apps, men hvis man har en der brukeren lager queryen selv, med custom group by, aggregering, osv., blir det vannskelig
Den kjøper jeg ikke helt uten videre. Jeg har ihvertfall laget nokså spesialiserte søkegrensesnitt tidligere med masse sånne verktøy og ikke hatt behov for å gi avkall på enveis dataflyt.
Det finnes sikkert tilfeller der man må gi opp ensrettet dataflyt og rene funksjonelle transformasjoner for å få den ytelsen man trenger, men ikke den skalaen det gjøres i vår industri.
en ting skal sies. Både med hooks i React og subscriptions i reagent, så blir dataflyten enveis. Bare sånn for å henge meg litt opp i det. "Enveis dataflyt" og "alle data på toppnivå" er ikke det samme. Så det blir ikke et sånt OO-graf-virrvarr med hooks/reagent
en hook i react er lokal til komponentet og kan bare sende data nedover, samme med subscriptions i reagent
da bruker jeg antagelig ordene mine feil, for "mange små maskiner som sitter på deler av dataene og lever i sin egen livsyklus og oppdaterer deler av UI-et" er ikke innenfor det jeg mener. 🙂
hvis man f.eks hadde sendt inn et atom til hele treet og endret på det dypt der nede som førte til at noe over den selv i treet rendret seg på nytt, så er man på OO-graf-kaos-kjøret, men det er heldigvis ikke sånn man gjør det i reagent 🙂
Mulig det ikke er nødvendig å gå bort fra enveis dataflyt, jeg bare har ikke sett på det som viktig. Vi har noen re-frame/reagent problemer, men det er ikke det.
men det blir jo ikke data driven programming og referentially transparent og alt det der på den måten. Men det blir enveis ihvertfall 😄
Ja, jeg tror jeg er enig med @U0MKRS1FX, fordi vi har omtrendt all data på topp nivå
Der tror jeg du traff spikeren på hodet, @isak. Du har ikke sett på det som viktig. Og det er jo problemet vårt her. Å klare å kommunisere hvorfor det er bedre.
Hvorfor er det bedre? "Nei, du jobber med data istedet for en objektgraf, også er det pure functions, og sånn." "Mja, har ikke egentlig noen problemer med objekter vi!"
Ja. Det er mange ting folk har tenkt var viktig over tiden. For eksempel det med property-based testing for UI, om.next med co-located, queries, osv. Jeg sier ikke at det ikke var viktig, men det har en kostnad som må vurderes.
hva er grunnen til å foretrekke å ha all tilstand på toppen i en enveis dataflyt, og gjøre det litt mere tungvindt å rendre sub-trær, vs å ha lokal tilstand i render-treet en enveis dataflyt, som gjør det trivielt å rendre sub-trær?
Hmm @magnars er du enig i det @U0MKRS1FX sa i at det å ha alt i app-state kan lett gjøres uten enveis dataflyt? Med enveis dataflyt, regner jeg med at du mener at alt sendes nedover direkte via props, ikke sant?
Nå er vi langt forbi stadiet hvor vi kommer til å forstå hverandre i denne tråden. 😅
mulig vi snakker forbi hverandre på dette med "enveis dataflyt", det jeg snakker om, uansett hva vi kaller det, er at data bare flyter nedover i GUI-treet, og sånn bli det både med all tilstand på toppen, og med lokal tilstand i komponentene
@U0MKRS1FX du kan ikke trivielt svare på “hva er tilstanden til appen min nå?“. Har implikasjoner for din evne til å forstå appen, testing, reproduksjon, feilsøking, etc.
der er jeg helt enig i prinsippet, men jeg må innrømme at jeg ikke synes det er så alt for vanskelig å legge inn noe logging i komponentet det gjelder, når jeg er i state-over-alt-verden
Det jeg ikke skjønner er hvordan man har blitt solgt på Clojure (og/eller ClojureScript), men krangler på at det å gjøre UI-et så funksjonelt og datadrevet som mulig er en god ting 😅
Ok hva med det eksemplet å lett legge til undo/redo uten å touche en set av components @U0MKRS1FX ?
å preppe alt på toppen kan jo sies å innføre kompleksitet og. Toppnivå må vite om behovene til alle children. Det kan bli vanskeligere å flytte rundt på ting. Ref å f.eks sende rundt en datomic db hvor man kan kjøre queries, mot for å måtte kjøre query først og vite om alle behovene til alt nedenfor
men kanskje man kan se på det som positiv kompleksitet 🙂 Det blir jo veldig transparent hva som foregår
Jeg tenker ikke på det som at man prepper ting til en spesifikk komponent. Jeg tenker på det som at jeg transformerer ALLE dataene mine til ett view på dem. Og så gir jeg dem til et komponent-tre for å rendre det.
jeg klarer ikke svare på spørsmålet ditt i denne tråden, @isak, men jeg har skrevet (ganske kort) om hva jeg mener med "ensrettet dataflyt" her: https://www.kodemaker.no/blogg/2020-01-enkel-arkitektur/ Det handler om mer enn bare "props" (hva enn det er for noe 😄)
@U0MKRS1FX Akkurat det med query som bestemmes av en komponent, men fremdeles respekterte enveis dataflyt ble løst av om.next. Men det ble veldig komplisert.
En klar ulempe med lokal state er at hotreloading funker dårligere? Du mister jo den lokale state’n?
Husker forøvrig jeg hadde en slags diskusjon m Eric Norman om dette: > That’s a great question. > > Re-frame and Reagent give you the best of both worlds. You can write pure components. Or you can write impure components. In my experience, pure components are great up until they are not. Reagent gives you a nice way to convert a pure function returning hiccup into a stateful component. > > But that brings up the question: when are pure components not great? > > I don’t know if I have a great holistic answer to this question, but in my experience, as UIs get more sophisticated, the data you have to flow through your functions becomes tightly coupled with the DOM structure. Let me explain with an example: let’s say you want to have a label that shows the currently logged in user’s name. That label appears down in a component deep within the main panel of the app. To make that work in a pure way, every component has to know the name of the user, all the way from the top, down through many layers, until that label. It is essentially global information, since so many components know about it. Now, the requirements change. The label needs to appear not there, but in a cousin tree. You have to reflow the name of the user to go down that other tree. The more distant the tree, the more components you have to touch. > > The solution in Re-agent is that that is simply global data, available via a named subscription. You can easily copy and paste the component from one tree to another, and not have to deal with re-flowing data. It is common enough for components to move around while an app is being designed that it can significantly reduce the development overhead--especially since the dom structure rarely corresponds to anything rational and stable. > > Having calculations in subscriptions is great because it lets you separate out the view from derived data. > > And after all that, I’m leaving out another important aspect when it does come up: being able to re-render only a small subset of the dom instead of the entire thing. This starts to be important with large doms, such as with thousands of spreadsheet rows. > > Finally, I think Re-frame is probably better classified as reactive programming instead of functional programming. A lot of the functional programming ideas are still there, but there’s the new idea of derived values (such as the dom) being a function of changing data. There’s an idea of a “current value”. > > I tend to think of Reagent components as having 2 sources of inputs: function arguments and subscriptions.
> En klar ulempe med lokal state er at hotreloading funker dårligere? Du mister jo den lokale state’n? Det er sant, men det er vist noen tricks man kan gjøre for å få det tilbake. (Ikke at jeg er for lokal state)
@U04V5VAUN Det er en god forklaring. Jeg tenkte også på det med en spreadsheet, fin eksempel der performance er kritiskt.
Kan jeg få et konkret eksempel på noe som er enkelt å gjøre i Reagent, vanskelig å gjøre med dumdom og Enkel Frontendarkitektur Som Funker (TM), og hva man ville gjort i stedet med EFSF(TM)?
Jeg henger ikke helt med.
Er det som forskjellen på Elm Architecture og React-greier? I Elm sørger typesystemet at det eneste en komponent kan gjøre er å sende en action? Og da kan man lage test : State -> Bool
?
Ideelt sett så skal datene som kommer ut av prepare være i UI-domenet, og ikke i det heletatt i appens/forretningens domene
Men i praksis så hender det at det lekker litt, kanskje særlig i de øvre lagene, ettersom det grøvste av layout handler mye om hvilke ting som skal hvor og kan være klønete å finne gode abstraksjoner for
Ellers må jeg si at resonnementet fra Eric Normand over leser som om det jeg driver med på jobb er både upraktisk, og yter dårlig. Det stemmer ikke med min erfaring.
Når det argumenteres for tilstandsfulle komponenter så er det alltid pga ytelse og fordi det er dumt at alle komponentene må vite om all data. Jeg lurer på i hvor stor grad disse argumentene har rot i praktisk erfaring vs teoretisk problematisering. Ytelsesproblemet er alltid en variant av "spreadsheet"/masse data, men de aller fleste apper har helt håndterbare mengder data, og du kommer lenger enn du tror før ytelsesproblemene trer inn. Når det gjelder å sende data nedover så opplever ikke jeg det som spesielt upraktisk eller vanskelig. Som tidligere nevnt tenker jeg på dataene som skal rendres som "UI-et, i dataform" - ikke som data til disse 700 forskjellige komponentene. Komponentene som sender data nedover plukker stort sett ut én ting som sendes til et subtre. Fordelen med denne modellen er at du når som helst kan sitte med hele datastrukturen for enhver tilstand i UI-et ditt i hånda. Det gir deg super powers og er verdt å jobbe litt for.
lurer på om jeg har en liten mental sperre her. Her og nå slo det meg at selve GUI-et er jo også bare data. Altså hiccup. Det visste jeg jo, men når jeg ser en :div så føles det ikke som data, men som noe annet. Litt knotete forklart kanskje. Men sånn sett er det jo "bare" tre lag? Først domene-dataene, det du skriver til, som er en database eller noen maps eller noe annet. Så transformeres de til noe som er mye mere GUI-data og har minst mulig domene i seg (prepare). Så transformeres det igjen til 100% GUI-data (altså hiccup og render-steget)
domene-data (read/write, flatest mulig, mest mulig query power) ⬇️ GUI-data (read-only, litt struktur) ⬇️ render-data (read-only, masse nøsting og struktur)
og for å ta det med CMS-en min igjen, så funker det helt fint å optimalisere der det trengs. F. eks disse hjemmelagde input-feltene mine skriver faktisk til domene-dataene på toppen men trigger ikke en prepare/render. De rendter seg selv via refs og maskineri, som er helt oversiktlig og fint, og nødvendig (fordi fps var lav når man skrev, ikke fordi premature optimization)
det er jo ikke noe rammeverk som bestemmer hvordan ting skal funke, så det er jo bare å lage seg det man trenger for å få til det man trenger
En vesensforskjell mellom UI-data og hiccup er at førstnevnte er en konsis strukturell beskrivelse av et grensesnitt, mens hiccup inneholder masse flyktige detaljer for å få rett design. UI-dataene har både en tydeligere struktur og er mer stabile over tid. Det er også disse dataene som gjør det mulig å gjenbruke de samme generiske komponentene for mange forskjellige domenekonsepter.
pluss at jeg tipper UI-dataene ikke nødvendigvis er strukturert for rendering heller? Hiccup får jo masse nøsting, men det er ikke sånn at UI-dataene representerer hiccup-nøstinga 1:1?
Nei, ikke på detaljnivå
nå ble det litt sånn utspørring her... 🙂 Jeg er veldig tilhenger av namespaced keys. Eneste unntaket er libraries som tar inn maps, og typ å sende inn options til en funksjon. Men alt av data som sendes rundt foretrekker jeg namespaced keys på. Både domene-data og gui-data egentlig. Tanker?
i domenet er det ihvertfall bra med namespaced keys, og det får man jo "gratis" om man bruker datomic/datascript
det følger kanskje litt den trestegs flyten. Domene-data 100% namespaced keys, UI-data en god del namespaced keys, hiccup 0% namespaced keys
@magnars du kan angre å ha tiltrukket min oppmerksomheten til tråden :) > Fordi det er en grunnleggende enklere modell. Helt enig med det! Jeg er i båten med Christian og Magnar her. Jeg vil bringe litt perspektiv fra Fulcro. Jeg har mye mindre erfaring med å bygge FE enn dere men det jeg har opplevd ledet meg til Fulcro som en mye bedre løsning. Og dens autor, Tony Kay, har masse erfaring med å bygge full-stack apps på denne måten og det tydeligvis fungerer for ham (& andre). Jeg har stor respekt for Tony og hans dybt design thinking. > å preppe alt på toppen kan jo sies å innføre kompleksitet og. Toppnivå må vite om behovene til alle children. (same thing that Erik Norman mentioned) > > @U0MKRS1FX Akkurat det med query som bestemmes av en komponent, men fremdeles respekterte enveis dataflyt ble løst av om.next. Men det ble veldig komplisert. Interessant å høre at Ch&M ikke opplever dette som et problem. Praksis <> teori :) Ellers prøver react-query å løse problemet i JS verden. I cljs er Fulcro den beste løsningen jeg vet om. Jeg vil adressere "Men det ble veldig komplisert." Om.next var komplisert for det var egentlig en forskningsprosjekt. Fulcro "streamlines" og forenkles det mye, siden den er laget for å skrive og vedlikeholde kommersielle apper. Mange tror at også Fulcro er komplisert - men det er en myte som jeg ønsker å fordrive i ClojureD :) IMO er den mindre komplisert enn hvilken som helst sammensetning av en UI lib + state management lib + data fetching lib. Nevneverdig - Fulcro er egentlig en "loose set of few core, many optional parts". Men nok om det; de interesserte kan lese mer på https://github.com/fulcro-community/guides/blob/split-mft/modules/tutorial-minimalist-fulcro/pages/ -> index.v2.intro.adoc Ang. diskusjon om hvor lagrer man form state - Fulcro har den i global state (så at ui=f(state). Når man endrer på et felt så kan man bruke et triks - om nødvendig! - så at bare input komponenten rendres på nytt. Men det er gjennomsiktig til utvikleren, dataene går fortsatt via global state, og neste full render vil fungere som om man ikke brukte trikset. Så den enkle modellen på utsiden og noen triks for bedre ytelse på innsiden. Ytelse & Big data - som nevnt, trikset er å ikke rendres masse unødvendig data som ingen menneske kan fordøye :) Fulcro hadde en optimizer renderer som bare re-rendret komponenter med endret data uten å rendres dens foreldre. Men det viste seg at i reelle prosjekter er ytelseforbedringen ikke verdt den ekstra kompleksiteten. Dvs ytelse er mye mer et teoretisk enn reel problem (men nyttig å ha "escape hatches" for når du virkelig har problemet).
> i reelle prosjekter er ytelseforbedringen ikke verdt den ekstra kompleksiteten. Dvs ytelse er mye mer et teoretisk enn reel problem (men nyttig å ha "escape hatches" for når du virkelig har problemet)
Premature optimisation... :)
For 10 min intro to Fulcro, if y prefer video https://youtu.be/UrpYLyGy4Lc
Tråder i Slack har det med å begrave interessante diskusjoner for de som ikke har deltatt i tråden, så tenkte bare jeg skulle gjøre oppmerksom på at det har foregått mye interessant prat i tråden over ☝️ 🙂
Har fulgt litt med på diskusjonen der innimellom slagene på kontoret i dag, men har ikke så mye å bidra med rundt temaet 😅
Jeg leste denne @magnars: https://www.kodemaker.no/blogg/2020-01-enkel-arkitektur/ Mitt intrykk (fra en re-frame bakgrunn) er at det løser noe som i min erfaring har vært et lite problem (de å forstå hvilken data brukes hvor), og introduserer et større problem - en global performance degradation som må da vurderes i hvert tilfelle i hver app om det er OK eller ikke, eller om en workaround (for eksempel "shouldComponentUpdate") rundt modellen må benyttes. En annen ting er at jeg ville tro det blir veldig tungvindt. Hvis jeg jobber med en "leaf" component som trenger mere data, må jeg da finne alle steder den blir brukt, gå gjennom hele "call stack" hvert sted og passe på at dataen sendes nedover. Enig at det blir lettere å se dataflyten, men det er jo en ganske ekstrem kostnad.
Men det er ikke første gang jeg har blitt fortalt at teknikker og teknologier jeg har brukt i mange år antagelig ikke fungerer i praksis, det pleier bare ikke skje på Clojure-slacken. 😛
Jeg tror du misforstår litt, jeg sier ikke "dette vil aldri funke", jeg bare tar opp ulempene. Det er ikke bare fordeler med den strategien. Før i threaden virket det som du synes det var rart at ikke alle var on-board med dette, så jeg prøver å gi et mere balansert persperktiv.
Min erfaring er vel heller at så godt som ingen gjør det på måten jeg prøver å fortelle om, ikke i JS/TS-verdenen, naturlig nok, men ikke engang i Clojure-verdenen.
Jeg kan si at det er ikke veldig tungvindt, og det er ikke store ytelsesproblemer, men på samme måte som med Clojure generelt så hjelper det fint lite å diskutere. Jeg kan si så mye jeg vil at "du blir vant til parentesene", "joda, selv om funksjonene ikke har side-effekter så får man faktisk gjort noe", og "nei, Clojure er faktisk veldig raskt, selv om det er en lisp" - men det hjelper ikke stort. Man må nesten oppleve det selv.
Det er også derfor jeg i hovedsak bruker tiden min på å vise frem hva som er bra, heller enn å prøve å overtale andre. 🙂
Jeg verdsetter at du deler perspektiven og erfaringene dine! Å overbevise folk er vanskelig / umulig men en åpen debatt er likevel veldig givende, IMO
Hyggelig å høre! Men jeg tror jeg kan bidra bedre ved å lage videoer og skrive bloggposter enn å diskutere kvelden lang på slack 😅
shouldComppnentUpdate er vel uansett implementert ut av boksen i alle gui-toolkits til cljs, håper jeg
men det blir vel fortsatt dyrt å gjøre shouldComppnentUpdate på keyup i en liste med tusenvis av elementer (?)
når man har mye nok data får man også problemer andre veien. I CMS-en jeg lager bruker jeg f.eks core.rrb-vector til å representere en flat liste med characters, fordi concat på to vectors (sette inn en character midt inne i lista) er O(N) og man skal ikke ha veldig mye tekst i et tekstfelt før man ikke klarer å svare kjapt nok på keyup på folk som skriver litt fort https://github.com/clojure/core.rrb-vector
jeg opplever også at "Magnar-pattern" funker fint, jeg bruker det. Og hopper ut og gjør ting mere direkte der det trengs. Som Magnar sier, ting som skal følge bevegelsen på musa f.eks. Jeg render text selection med dumdom, men i en egen verden isolert fra resten av appen, så det bare er selve de blå strekene som viser selected text som rendres på mousemove
samme med sortering ved drag & drop, lager en egen datastruktur for å sjekke mot på mousemove, og når det trigger en resort, rendres det på nytt igjennom appen på vanlig måte ved å sette state
så det jeg sier er vel at jeg kan bekrefte at patternet holder mål, og at kjapt snappy GUI ikke løses med reagent, det går dypere
tror også at det stemmer at akkurat det å ha en liste med tusenvis av elementer og bare oppdatere en av de er mindre jobb å få til med reagent. Men erfaringsmessig er det ikke bare tut og kjør med sånne GUI-er, blir fort en del custom greier og knot og optimalisering, så "overheaden" man eventuelt får med "Magnar-pattern" er ikke noe rødt flagg i min bok ihvertfall
@isak selvfølgelig er det ikke "bare fordeler", men det er en kjempefordel der som jeg ikke forstår helt hvorfor flere ikke ønsker seg 😊
> Jeg ville tro det blir mer tungvint Vel, det kan jeg si deg av årevis med erfaring at det ikke gjør. Det blir åpenbart noe mer eksplisitt, men det er i min bok en fodel. Av og til blir det også litt busywork, men ikke noe som tar betydelig med tid. Dette er et argument jeg ofte leser og som ofte er på formen "det virker veldig upraktisk" (altså kanskje med noe manglende erfaring), som jeg også skrev litt om i megatråden over
Jeg tror dere undervurderer litt hvor mye erfaring de fleste har med den pattern. Man kan jo gjøre samme pattern i re-frame - det er bare å bruke færre subscriptions. Enig at de blir vannskelig å overbevise folk, de fleste har jo erfaring med noe som de synes funker. Jeg kan godt gi meg der også, forstår at det blir pinlig å diskutere for folk.
Godt mulig jeg undervurderer, men når du skriver "jeg vil tro" så høres det mer ut som gjetning enn praktisk erfaring.
Pinlig? Kom igjen, a.
Ganske sikker på at han ikke syns det var pinlig å diskutere, ja 😊
Hundrevis av rader med 10+ editerbare kolonner, da ble det litt tungt å bare sende alt ned.
Jeg forstår at man kan jobbe rundt det med onblur, pagination, local state, osv, men det er jo fint hvis man slipper.
Til info så mente jeg ikke at det var pinlig å diskutere (en litt rar ting å syns?), men at det ikke er en effektiv form for overføring av idéer, og jeg i dag hadde brukt for mye tid og krefter på noe som har lite payoff. 🙂
Ok, jeg har bodd i USA en stund, jeg misforsto sikkert denne: > Skjønner at jeg gikk på en smell her i dag, da.
Stemmer nok, den må ses i sammenheng med setningen over, hvor jeg prøvde å formidle at jeg vanligvis forsøker å etterfølge "show, don't tell".
Er forøvrig i Bergen og kom dit med fly. Og på flyet kom jeg på ideen om at jeg kanskje skulle se om jeg klarte å implementere zombie-ts? Bare for å se hvordan det ville blitt?
https://clojurians.slack.com/archives/C061XGG1W/p1647977516090889 Jeg har lest både "En enkel frontendarkitektur som funker" og "Samspill mellom generiske UI-komponenter" før. Skjønte noe, men det var mye som ikke ga mening. Etter dagens Slack-meldinger gir det mer mening.
problemet er at Magnar har klart å koke ned det som kunne vært en bok på 300 sider til en bloggpost :) ❤️
er et fint pattern, det. Skulle ønske mere informasjon var tilgjengelig i formen setning ➡️ avsnitt ➡️ artikkel ➡️ bok
nå trenger vi bare boka :thinking_face: @christian767 på tide med bok nummer to? 🥳🥳🥳