Morn!
Morn!
Morn!
Morn!
Ikke direkte Clojure-relatert, men jeg drister meg til å lenke denne her allikevel: https://parenteser.mattilsynet.io/backlog/
Jeg har skrevet en liten oppfølger med noen alternativer: https://parenteser.mattilsynet.io/livet-uten-backlog/
Hør, hør! Tar med meg denne og deler i org'en min 😊
jo mere jeg tenker på dette, jo mere absurd virker backloggen. "La oss ta vare på alle antagelsene om en fremtid vi vet nesten ingenting om, som om vi har noen anelse om hva som er viktig de neste månedene/årene"
er det noen skjæringspunkter her? Har dere endt opp med å glømme noe viktig etter dere kastet backloggen? Eller oppleves det egentlig som utelukkende en fordel å ikke ha den?
Vi har operert uten backlog i to år, og har ikke glemt noe viktig enda 😊
Denne var fin, vi gjorde en tilsvarende øvelse i teamet nå nylig. Skal dele den hos kunden 🤩
har dere vurdert "digital tavle"? Så man kan få en påminnelse om ukens store linjer om man har hjemmekontor en torsdag?
Jeg tenker at Trello er ideelt for slikt. Har prøvd forgjeves å få det inn hos oss i lengre tid, men konsensus er at jira-historikken/backloggen er for viktig. (trello gir også historikk og backlogg hvis man ønsker det, btw)
Trello er for mye tooling for meg. Vi skriver på tavla, og så noterer én av oss punktene i en punktliste på en dedikert kanal på Slack, #team-mat-ukesmål
Fredagsmøtene våre er alltid digitale, for det er den store joggebuksedagen 😄
Veldig enkelt med Slack ja! Men synes Trello har såpass lite overhead at det gir verdi. Eneste man trenger er en login, og deretter: • lag et board • skriv inn noen oppgaver • gjør hva man vil
Problemet mitt er det siste punktet 😄
åja? tenker det er helt flott jeg 🙂 stor fleksibilitet til å velge hvordan man vil at oppgavene skal flyte selv i teamet, og hvis man ikke trenger å tracke oppgave flyt, så trenger man ikke å lage swimlanes heller.
Jeg vil ikke ha et ticketing-system 🙂
skjønner
bare mål, det gir jo mening det.
💯. Kuriositet: jeg finner mye stæsj på bloggen min om "finn det viktige, fokuser på det, fjern det som distraherer, nyt fokuset".
Fokus på fokus 🎯
Hvor er cover-bildet fra, @christian767?
The Log Lady fra Twin Peaks!
Jeg er veldig fornøyd med valg av bilde 😁
Nydelig! Har faktisk ikke sett serien siden den gikk på tv, og har ennå ikke fått sett den nye. På tide å gjøre noe med 🙂
(jeg hadde en ordentlig Lynch-periode på begynnelsen av 2000-tallet, men ble litt skremt og kurert da Inland Empire kom - dvd'en ligger fortsatt uåpnet i en kasse i kjelleren et sted)
Haha, ja den var ikke så vellykket. Litt mye Lynch i monitor. Siste twin peaks lider av samme problem. Men originalen er episk bra.
Morn!
Morn!
god morgen!
Heisann!
Vi har jobbet med å lage en ny applikasjon i det siste. Jeg har ønsket å unngå et problem som vi så ofte opplever: at testsuiten begynner å ta lang tid å kjøre etter hvert som antallet tester øker. Det er jo de hersens "integrasjonstestene" som ødelegger, så klart. Så: ingen integrasjonstester, bare selskapelige og overlappende tester. Altså enhetstester for funksjoner som kaller andre funksjoner. I bunnen (eller i kantene, om du vil, avhengig av hvordan du ser det) finnes små innebygde stubber som later som de er en fasade mot den side-effektfull verden utenfor (når det trengs - det aller meste testes som del av den funksjonelle kjernen). Resultatet så langt? Lynkjapp respons fra testene:
God lørdag! Grått i Oslo, gitt.
Inspirert av testene deres, @msolli, og en forbifarten-kommentar fra @smestad, tok jeg en blikk på hvordan vi kjører testene våre i Mattilsynet.
Å kjøre alle testene våre på Mac-en min tar 74 sekunder. På CI tar det (per nå) lenger tid. Det er kjempebra sammenliknet med mange andre systemer. Men 74 sekunder kunne vært mindre!
Så jeg gjorde en innsats for å parallellisere testene våre. Vi har jo flere kjerner på Mac-en, det må da gå fortere å kjøre flere samtidig? Testene våre er imidlertid ikke trådsikre — så hvis vi parallelliserer testene med tråder, får vi falsk-positiver. Så jeg gikk for parallellisering via separate JVM-prosesser i stedet.
Etter litt prøving og feiling ga 4 JVM-prosesser best tid, og jeg landet da på 54 sekunder. Mesteparten av denne tiden er integrasjonstester (er jeg ganske sikker på). Og en ting som gikk opp for meg er at hvis selve koden din er parallellisert (og testene ikke er tungt begrenset av IO), er det nesten optimalt å kjøre testene én etter én! Hvis du ikke har mange datamaskiner du kan bruke, da.
Den andre tingen som gikk opp for meg, er at jeg ønsker meg jo egentlig resultatet deres — at vi ikke trenger tester som spinner opp hele systemet, fordi vi har god nok dekning uten.
Du skriver at dere gikk for litt mocking på kanten av systemet.
Selv har jeg tenkt mye på kanaler. Hvis vi bruker kanaler (feks core.async-kanaler) for interaksjon med omverdenen, har vi jo indireksjonen vi trenger? Uten å bruke mocks? Så kobler vi kanalene til å gi ekte effekter og koeffekter i prod, mens vi kontrollerer kanalene i test. Sammen med litt monitorering er det kanskje godt nok?
Hvis man skal få til noe sånt, må man nesten kunne kjøre hele systemet sitt som en reduce. Som krever ganske mye innsats. Og hvis man også kan "deffe opp" en tilstand, for så å lage flere nye gyldige tilstander fra den tilstanden, noe ala:
(def tilstand (lag-starttilstand testdatasamling))
(def tilstandA (system/med-handlinger tilstand [{#_"handling 1... "} {#_"handling 2 ..."}]))
(def tilstandB (system/med-handlinger tilstand [{#_"handling 3... "} {#_"handling 4 ..."}]))
Hvis disse alle kan "deffes opp", og operasjonen system/med-handlinger er så rask som den kan bli, får man vel god kontroll på helheten? Datomic har allerede datomic.api/with som tar inn en db og gir en ny db.> I et FCIS-oppsett vil effektene bli håndtert i en sentralisert lokasjon, ikke sant? Slikt sett tenker jeg at interfaces/protokoller gi mening Du trenger i alle fall noe indireksjon! Vi bruker ikke protokoller, interfaces eller multimetoder i koden vår, fordi vi ikke liker typer som flyter rundt i minnet — det blir kjedelig med instanser av gamle typer når man endrer en implementasjon, plutselig tryner noe. Med ren data og rene funksjoner er den biten lettere. Se for deg https://github.com/cjohansen/nexus sin action dispatch, på backenden. Eksempel fra Nexus sin README:
(require '[nexus.registry :as nxr])
(require '[replicant.dom :as r])
(defn save [_ store path value]
(swap! store assoc-in path value))
(defn increment [state path]
[[:effects/save path (+ (:step state) (get-in state path))]])
(defn render [state]
[:div
[:p "Number: " (:number state)]
[:div
[:label "Step size: "]
[:input
{:value (:step state)
:on
{:input
[[:effects/save [:step] [:fmt/number [:event.target/value]]]]}}]]
[:button.btn
{:on {:click [[:actions/inc [:number]]]}}
"Count!"]])
;; App state
(def store (atom {}))
;; Handle user input: register effects, actions and placeholders.
;; If you don't like registering these globally, the next section
;; shows how to use nexus.core, which has no implicit state.
(nxr/register-effect! :effects/save save)
(nxr/register-action! :actions/inc increment)
(nxr/register-effect! :effects/save save) blir analogien til en protokoll-registrering, bare med data i stedet for protokoller.
> Når det gjelder kjøretid så må jeg si at 74s høres mye ut? Hvor mange integrasjonstester har dere?
Med tanke på at testene våre muliggjør deploys så ofte vi vil, og kjører alt som passerer testene rett i prod, er jeg godt fornøyd! I tidligere kodebaser har jeg vært vandt med en tyngre deploy-loop, så for meg er det en forbedring. Men som jeg var inne på over, raskere er utvilsomt bedre, hvis vi kan få det raskere!Forskjellen på eksempelet over med register-effect! og f.eks. protokoller er at du har en løst eller svakt definert definert kontrakt for systemet. Det er helt ok i et system med kun én implementasjon, men dersom du skal ha flere implementasjoner (slik det @msolli snakker om med test-stubs) så ville jeg foretrukket en veldefinert kontrakt. Og implementasjonen / definisjonen av f.eks. en protokoll vil nesten sjeldent "gå ut på dato" i et kjørende utviklingssystem ettersom det er den delen av koden som endres minst hyppig.
> Med tanke på at testene våre muliggjør deploys så ofte vi vil, og kjører alt som passerer testene rett i prod, er jeg godt fornøyd! Det kjøper jeg 💯
Har ikke rukket å reflektere så veldig mye over dette. I et FCIS-oppsett vil effektene bli håndtert i en sentralisert lokasjon, ikke sant? Slikt sett tenker jeg at interfaces/protokoller gi mening, og at man kanskje kan ta det enda et steg videre og definere hele effekt-systemet i ett og samme grensesnitt 🤔 Når det gjelder kjøretid så må jeg si at 74s høres mye ut? Hvor mange integrasjonstester har dere?
Også null feil, da!
Sånne tester er det så deilig å jobbe med! 😇
Man må liksom oppleve det for å sette pris på det. 20 sekunder å kjøre testene? Akseptabelt, kanskje. Men under 1 sekund? Det ligger til rette for flyt på en helt annen måte.
Interessant nok så tar det 6 sekunder å kjøre 1 frontend-test med vite/vitest i prosjektet vårt.
Det er altså boot-steget som tar tid.
(transpilering)
Jeg må nevne at dette er en watcher – tiden som står der er ikke inkludert oppstart av JVM og lasting av Clojure-kode, det tar mangfoldige sekunder. Og vi slipper ikke unna "transpilering" i Clojurescript heller, men det er et triks: CLJC kan bli både til JVM-bytecode og Javascript! De fleste av disse testene er faktisk "frontend"-kode, men skrevet i CLJC-filer. Altså kan koden testes i JVM. Den frontend-testen, gjør den noe med nettleser-API-et, eller er det en enhetstest?
Ren enhetstest
Men vi bruker typescript og det har en større påvirkning i seg selv
Skjønner - det tar bare så lang tid å transpilere og holde på før testen kan kjøres.
Dette er noe av det jeg savner med frontendutvikling i typescript: kjøre en test adhoc på tilsvarende vis som i et clojure-repl. Instant feedback.
👀 Morn!