31. Maj 2024

Kode & copyright

Disclaimer: Jeg er ikke jurist, blot interesseret i dette felt. Du er velkommen til at skrive til mig, hvis der er elementer i nedenstående, der bør rettes/præciseres.

En dag på Github…

Tænkt eksempel: Du ser en stump kode på Github. Koden har ingen licens tilknyttet - hverken i nogle af sourcekode-filerne, eller i en LICENSE fil i repo’ets rod. Er den så Open Source, og må du så kopiere koden, og gøre med den, hvad du lyster?

Jeg har nok allerede hintet svaret: Givet Githubs funktion som kodedelingssite, så burde det være et rungende ja, men det er - desværre - ikke sådan verden virker.

Svaret er desværre et nej.

Hvis ikke du får eksplicit lov til at lave ændringer og videredistribuere koden via en åben licens a’la BSD, MIT og GPL eller lign., så er koden 100% repository-ejerens ejendom. Githubs dokumentation nævner:

… You’re under no obligation to choose a license. However, without a license, the default copyright laws apply, meaning that you retain all rights to your source code and no one may reproduce, distribute, or create derivative works from your work.

Kigger man i den danske lov Ophavsretsloven, har “edb-programmer” samme status som et litterært værk (§1, stk. 3) og den, der har ophavsretten er den, der frembringer værket (paragraf §1).

§ 1. Den, som frembringer et litterært eller kunstnerisk værk, har ophavsret til værket, hvad enten dette fremtræder som en i skrift eller tale udtrykt skønlitterær eller faglitterær fremstilling, som musikværk eller sceneværk, som filmværk eller fotografisk værk, som værk af billedkunst, bygningskunst eller brugskunst, eller det er kommet til udtryk på anden måde.

Stk. 2. Kort samt tegninger og andre i grafisk eller plastisk form udførte værker af beskrivende art henregnes til litterære værker.

Stk. 3. Værker i form af edb-programmer henregnes til litterære værker.

Så derfor, selvom du befinder dig på Github, så betragt al kode som “nok se, men ikke røre”, medmindre der er en åben licens vedhæftet.

Det ville ellers forenkle verden, hvis upload til et offentligt kodedelingssite automatisk betød: “Jeg/vi giver min/vores kode til verden, gør med den, hvad I vil”, men det er åbenbart brugernes egen hovedpine ikke at ende i et juridisk minefelt.

23. April 2024

En stensikker cachebuster!

Har du nogle gange undret dig over, at dit CSS og Javascript-indhold ikke er blevet opdateret korrekt, når du har lavet opdateringer på dit website? Når en browser forespørger på en url, sender webserveren to headere “Last-Modified” og Etag-information tilbage, der fortæller browseren om det er tid til at opdatere indholdet, der ligger i browserens cache.

Det burde virke som smurt - det gør det desværre ikke altid. Ej heller selvom du f.eks har aktiveret “Deaktivér cache” i Firefox’ webinspector.

Aber dann haben wir anderen metoden! ;-)

Hvis du klistrer en parameter på dit stylesheet-url, så fortæller du browseren, at det her element “skifter form”, så den må ikke cache indholdet.

<link rel="stylesheet" href="stylesheet.css?v=1">

Parameteren kan du så opdatere, når du lægger et nyt stylesheet eller Javascript op med ændringer, eller du kan være kreativ og smide en stump kode på, der genererer et tilfældigt tal ved hver pageload, så slipper du for at justere tallet/tallene manuelt.

17. April 2024

Frem med projekt-øksen

Det er desværre tid til at svinge øksen over nogle af mine hobbyprojekter. Det er selvfølgelig hverken Handicapguiden.dk eller Fediverset.dk, der er tale om, men nogle lidt mere generelle projekter, der har lagt brak i op til 1 år.

Et gennemgående problem, for min hjerne i hvert fald, er at mine mange sideprojekter ligger i baghovedet og fylder, også selvom de er i dvale. Jeg ville gerne arbejde på dem allesammen og idégenererer derfor indimellem, selvom jeg ikke rører projekterne. Så for at fokusere, så må jeg mærke efter, hvad jeg brænder mest for, og rydde op.

Med tanke på, at der er særligt to projekter, der ligger langt væk i min bevidsthed, så er der to projekter på huggeblokken.

De to projekter, jeg tænker på, er hhv.

  • Scriflow
  • Untitled Spacegame

Jeg beskriver dem herunder, for det er ikke sikkert, at du har set mig nævne projekterne før - og det kan være, det kan tænde en gnist, så du får lyst til at udvikle noget lignende.

Scriflow (kodenavn)

Teknik: Go-backend og en React-frontend med FabricJS.

Et potentielt stort online DTP-projekt, inspireret af Scribus Open Source DTP-projektet, som jeg synes mangler en clouddel. Min tanke var, at f.eks foreninger og mindre virksomheder kunne bruge løsningen til at designe deres tryksager ganske gratis, og så kunne man bage en PDF som kunne downloades eller sende filen til tryk. Konceptuelt og teknisk synes jeg løsningen er spændende.

Jeg er ikke helt “ny” i forhold til at lave den slags: Tilbage i 2005-2006 lavede jeg to mindre, lignende løsninger for to lokale virksomheder, der havde behov for hhv. at printe labels og lave specialdesignede skilte. Løsningerne dengang bestod af en Adobe Flash-baseret frontend og ASP.NET-backend, så Scriflow ville være et naturligt step fremad imod et mere generelt produkt, baseret på moderne teknologier (heldigvis kan vi i dag undgå at kræve at folk skal installere bestemte browserplugins…).

Scriflow tog sin begyndelse, fordi jeg vil gerne hjælpe med minimere den byrde, det er at lave tryksager. Og med en webplatform, så er det nemmere for f.eks en forening at lave arbejdsdeling mellem to eller flere medlemmer, når designværktøjet blot kræver en browser.

Valget af sproget/platformen Go til backenden var lidt tosset, og valget skyldes nok mest min egen lyst til at arbejde med Go, for du skal have din egen server for at kunne afvikle det hele. Trods Python og Gos popularitet, så er der praktisk talt ingen danske webhosts, der beskæftiger sig med andet end PHP og Microsofts ASP.NET. Med tanke på knappe økonomi- og mandskabsressourcer i mange mindre foreninger, så ligger egen server nok ikke højt på ønskelisten. Ultimativt skulle jeg så selv hoste en server og evt. finde en bæredygtig forretningsmodel, men jeg kan bedst lide at udvikle, driften må andre godt tage sig af :-)

Jeg var sideløbende i gang med at definere rammerne for en PHP-backend API, men Go-backend’en trak mest, så jeg endte med at slette PHP-implementationen af serversiden ret hurtigt. Uklogt.

Prototypen kunne loade dele af en Scribus DTP-fil ind og præsenter basal indhold, men der var stadig en lang vej til et færdigt produkt. Særligt Scribus’ filformat er noget rod: Nogle XML-noder skrives med stort, andre med småt. Nodernes attributter er ikke altid beskrivende for, hvad de gør, så der var en del trial and error involveret, hvis jeg ikke kunne gætte det.

I bagklogsskabens lys skulle jeg have valgt definere mit eget interface udfra en generel datastruktur, og så føde data den vej. og så hhv. eksportere/importere Scribus-indhold o.a. ind i det format fremfor for at bruge Scribus’ filformat som “backbone”.

Det er generelt en god idé at basere sit dokumentformat på en ISO-standard, hvis man kan, fordi hjemmesnedkererede formater kan ændre sig med lynets hast, alt efter hvor bagudkompatibel projektet ønsker at være. Jeg lærte også noget der :) Fra et fugleperspektiv er filformater jo bare data med forskellige egenskaber. Jeg tror idéen med en generaliseret struktur kunne have virket.

“Om lidt” kan man givetvis compile Scribus til en WebAssembly-runtime (f.eks wasmer) og afvikle Scribus hvorend man har lyst, så der er faktisk ikke ret meget incitament til at forsætte med Scriflow i dens nuværende form. WebAssembly-platformens største akilleshæl er, at afviklingsmiljøet ikke understøtter multithreading, men det arbejdes der intenst på at få løst I sit corrected… WebAssembly Multithreading, se her.

Hvorfor ikke bare bruge Canva, spørger du måske?

Joh, Canva er da ultracool. Men der bør altid findes alternativer til globale cloud-produkter, så folk har noget at vælge imellem, hvis de vil noget andet. Og jeg mener self-hosting er et absolut must. Cloud-løsninger er fint som tilvalg, men vær opmærksom på, at de kan ændre pris- og produktvilkår med lynets hast. Hvis du bliver uenig med en udbyder af et Open Source-cloudprodukt har du altid muligheden for at hive dataene hjem og hoste løsningen selv.

Er du en del af en forening eller en lille virksomhed, så vil du gerne have at de produkter, du anvender ikke ændres grundlæggende over tid, og dermed tvinger dig til at ændre din arbejdsrutine. Der har Open Source en af sine forcer, fordi et projekt ikke nødvendigvis behøver følge industritrends. Når det så alligevel sker, sker det ofte med respekt for bagudkompatibiliteten.

Guleroden i Scriflow ville være et væsentligt simplere interface end tilfældet er i Scribus. Til gengæld ville Scriflow ovenpå en WASM-runtime betyde et konsekvent udviklingsmiljø, hvor man for det mest kan undgå at skulle “swappe” frem og tilbage mellem forskellige platforme, og jeg ville undgå at bygge til noget, der er et “moving target”. React vNext kunne i teorien se helt anderledes ud i morgen, end det gør i dag. Jeg priser mig lidt lykkelig for, at jeg ikke sprang på AngularJS sådan for alvor (v1 og v2 var vildt forskellige).

Jeg kiggede lidt på GIO til Go som GUI-lag, men var ikke helt tryg ved at skulle bruge et projekt, der ikke er nået v1.0 endnu. Selvom et projekt sagtens kan være stabilt allerede pre-1.0, så kan man i mange tilfælde godt forvente, at API’et ændrer sig fundamentalt undervejs.

Det er muligt, jeg bygger Scriflow igen i fremtiden, for jeg synes som sagt, at konceptet er spændende. Men så bliver det et bundkonservativt, homogent udviklingssetup. Da som før nævnt, at mange foreninger og mindre virksomheder vælger et simpelt PHP eller .NET-webhotel er det oplagt at bygge backenden på de platforme. Med et Docker-setup som muligt tilvalg til mere avancerede opsætninger/integrationer. Ah, ja - drømme er gratis.

Untitled Spacegame

Teknik: Godot, Rust/C-backend

Nok det projekt, der er nemmest at smide på blokken, for jeg mistede interessen helt og aldeles.

Jeg havde en idé til en Open Source spaceshooter a’ la Elite Dangerous, som man kunne spille både on- og offline. Problemet med moderne kommercielle spil såsom ED er, at de ofte kræver en server - og når udgiveren slukker den, så godnat, no more ED fun… Ift. ED så vil opensource-community’et nok stable en alternativ server på benene, som de gjorde med Star Wars: Galaxies. Men det kunne være fedt at skabe et community omkring en rigtig FOSS-spacesim, og ikke “en andens lukkede miljø”. Det er bare federe at have kildekoden, og derfra kunne udvikle spillet i forskellige retninger.

I forhold til en space shooter, må jeg nok sande, at jeg ikke aner en skid om 3D-grafik :-D. Jeg har selvfølgelig studeret emnet ret intenst, og har lavet lidt prototyper i Godot. Men jeg er efterhånden en halvgammel mand, og orker egentlig ikke at skulle kaste mig over et nyt område, og al den matematik, åh nej da… Hertil kommer, at jeg skal lære at 3D-modellere, hvis jeg skal lave nogle fede objekter såsom fly og planet-inventar. Måske kunne jeg få nogle interesserede til at bidrage henad vejen - men jeg vil heller ikke lege projektkoordinator, og vil langt hellere programmere. Bottomline, jeg lod mig nok rive med af idéen om et fedt slutprodukt i stedet for at overveje, hvad et sådan projekt egentlig kræver, hvis man pin’er det ud i detaljer.

Jeg synes egentlig, jeg havde afgrænset projektet fornuftigt ift. at kunne stable en prototype på benene: Lav en planet (Mars). Rendér Mars på baggrund af NASAs højdekort. Lav en mand/kvinde-model, der kan spankulere rundt. Byg en flymodel. Næste trin: Lav et univers. Jeg udforskede procedural generation, men tænkte det i vanlig Mass Effect-stil ville være bedre at holde antallet af planeter på et minimum. Elite Dangerous er en fænomenal spacesim, men føles stor og tom, fordi universet er gigantisk. Det fungerer godt på papiret, men ikke i et multiplayerspil. Til sidst: Smæk det hele sammen - i teorien forholdsvis simpelt, og så i praksis alligevel ikke… Skal man nogensinde gennemføre et projekt, så er afgrænsning nøglen, ellers kan du udvikle i 5 år uden at få noget udgivet (been there, done that). Jeg udvikler f.eks Handicapguiden i små ryk (iterationer), for ellers tror jeg, sitet havde gemt sig på min harddisk endnu.

Allerede her, kan det måske mærkes, at “Untitled Spacegame” var omfattende - jeg har allerede investeret en masse tid ift. at lære Godot at kende, og selvom jeg synes det er vildt cool, så må jeg begrænse mig. Der er så mange nye aspekter, jeg skulle lære, så mange forsøg.

I øvrigt kan du til enhver tid hente OoLite (open source) eller købe X4-serien (kommerciel closed source), hvis du skal have en solid spaceshooter, der fungerer offline. Online, ja - der kommer jeg lidt til kort, hvis jeg skal pege på en Open Source-løsning. Findes der overhovedet nogen? Skulle jeg bygge en OSS-variant, så ville den nok være inspireret af No Man Sky, for jeg synes designet og de afslappede hardwarekrav passer godt til lidt casual gaming.

Chop chop! Og så laserfokus. Jeg kan allerede nu afsløre, at jeg kommer til at brede Handicapguiden meget mere ud. Men mere om det, når der er noget at kigge på. Som en lille cliffhanger: Jeg brugte ordet hybrid-app under beskrivelsen af Scriflow, den sti har jeg tænkt mig at følge endnu mere. As always.. Stay tuned.

15. April 2024

Brug UUID’er i din database

Internettet bugner med guides omhandlende hvordan du lærer at programmere. Desværre, så er der et kæmpe gab fra begynderguides til de mere avancerede emner. Hvad med de små “cowboy-tricks” som guides ikke lærer dig? Får vi bragt dem på bane, får vi ultimativt bedre IT-løsninger. Jeg kalder dem cowboy-tricks, fordi “best practice”-terminologien ikke rigtig holder særlig længe i IT-branchen: Det der anbefales i dag, kan være yt allerede i morgen.

Eksempel: Man kan stadig finde 20 år gamle PHP-guides på nettet, der instruerer folk i at bruge den uddaterede MD5-hashingalgoritme. Det er lidt trist, når den slags guides ofte er nybegynderes første kontakt med webprogrammering, for så får man ofte den opfattelse, at det er sådan, man gør. Se istedet password_hash().

Programmørfællesskabet Stack Overflow er der, hvor du finder de friskeste tråde omkring forskellige aspekter ved programmering. Finder du de tråde, så læs dem, det er der man virkeligt lærer: Når folk argumenterer for, hvorfor de vælger eller fravælger den løsningsmodel, de eller andre brugere har præsenteret i forumtråden. Og det er måske den bedste hjælp, når vi giver viden videre til andre. Det, der er særligt godt ved StackOverflow, når sitet viser sig fra sin bedste side, er at folk gerne samler årgamle tråde op for at tilføje opdateret viden.

Nå, men tilbage til UUID’erne…

Begyndelsen

Noget af det første du lærer i en guide, er hvordan du sætter din database op, sammen med den programmerings-platform, du nu interesserer dig for. De lærer dig at sætte en ID-kolonne op med fortløbende autonummerering og en primærnøgle, såsom:

ID Navn
1 Anna
2 Gylda
... ...

Det er fundamentet for alle databaseprojekter. Men midt i al simpliciteten, så slipper de fleste guides ret ofte tøjlerne, der hvor man går fra teori til praksis. Og det er et problem, fordi en database, hvor man identificerer de enkelte poster via et fortløbende ID er irriterende besværlig at arbejde med, hvis den skal kombineres med andre datakilder.

Sov godt om natten

Forestil dig, at du er ved at programmere et nyt artikelsystem på en hjemmeside. Du har en tabel i din database med flere tusinde rækker. Fra 1 - 1000. En dag kommer din chef og vil have dig til at kombinere den gamle artikeltabel med en anden tabel, for I har lige fusioneret med et nyt firma. Men der er et problem: Den anden artikeltabel har også rækker fra 1 - 1000.

Løsningen vil være, at de friskeste data gives ID’erne 1001 og fremefter… I mindre setups, hvor data ikke nødvendigvis skal ordnes kronologisk vil det ikke være et problem lige med det samme, men det er alt andet lige en skrøbelig løsning.

For du har jo normaliseret databasen, ikke? ;-) Skal du stadig have sammenhæng i dine data skal poster i evt. afledte tabeller også have det nye fortløbende ID, så det er tungen lige i munden ved kørsel af en dataimport. Du skal være 100% sikker på, at der ikke er dublerede Id’er. Hvis din tabels ID-kolonne har en primærnøgle, så kan du være sikker på, at databaseserveren sender eder og bespottelser i din retning, hvis den importerer et ID, der allerede findes.

Der må da være en lettere metode, der kan sikre din nattesøvn?

UUID’er to the rescue!

UUID’er - Universally Unique Identifier (UUID) - er unikke nøgler på maks. 128 bits længde. De ses ofte repræsenteret som en tekststreng på 32 karakterer hexadecimalt - f.eks 550e8400-e29b-41d4-a716-446655440000, men kan grundet makslængden på 128-bit også repræsenteres udelukkende som heltal. Det gør databaseserveren MariaDB/MySQL f.eks, og det forvirrede mig i starten.

Hvis du er masochist-typen kan du endda repræsentere et UUID binært med 0′er og 1-taller. Men så er vi vist ude i selvpineri, det kan jeg ikke se nogen fornuftig idé i ;-) I Assembly begyndte man også at bruge hexadecimal notation, fordi det var kortere og nemmere at arbejde med end binær notation.

Intet sammenfald

Givet en 128-bit størrelse, så er det meget usandsynligt, at to genererede nøgler nogensinde vil være ens. Wikipedia nævner i et afsnit om UUID’er, at blandt 103 trillioner generede UUIDv4-strenge, så er sandsynligheden for et nøgle-sammenfald 1:1.000.000.000 (1 milliard).

Ergo kan vi bestemt godt bruge dem som vores fikspunkt for datafletning. Du får en databasepost med en kolonne hvor data, der refereres til, altid er unikt og det bliver yderligere en fordel og et absolut must, hvis du en dag skal arbejde med data, der befinder sig i et servercluster, hvor forskellige servere udveksler data med hinanden (aka. distribuerede data).

Du kan også med fordel bruge UUID’er, når data eksporteres ud i et andet format, såsom JSON eller XML, fordi du kan referere tilbage til den oprindelige post. Det kan der så være sikkerhedsmæssige overvejelser til, at man IKKE vil gøre, men det er op til den, der implementerer IT-løsningen.

Lidt slutovervejelser

Måske synes du det er overkill at bruge UUID’er i dit projekt, men det er altid fint at tænke langsigtet, også selvom dine projekter starter med at være små og afgrænsede. Måske får du en dag behov for at skalere op og bruge en distribueret databaseløsning, så er det et absolut must, at du kan identificere dine data via en unik identifier på tværs af noderne i dit servercluster.

Selvfølgelig skal du overveje om det er umagen værd, og der kan være ydelsesmæssige ulemper ved at bruge UUID’er som primærnøgle, fordi størrelsen af UUID-datatypen er 4 gange større, end hvis du vælger at indeksere en kolonne med heltal (128-bit vs 32-bit) og det er også omstændigt at referere et UUID, hvis du ofte JOIN’er resultater på tværs af flere tabeller. Men om det er et ydelsestab, der er til at bære eller ej, det kan kun en test afsløre.

Jeg plejer at helgardere ved at bruge både en autonummereret ID-kolonne og en UUID-kolonne, der ikke indekseres på, så er både jeg og databasen glad, for så er der forskellige muligheder for at referere og indeksere samme datapost.

For at opsummere hele opslaget: Brug kun et fortløbende heltal som ID til at referere til poster internt i databasen. Det id bør på intet tidspunkt eksponeres ude i det fri. Skal du referere til en databasepost ifm. din programmering, så benyt altid det oprettede UUID.

Kildelinks

Wikipedia: Universally unique identifier
Programmørforum: Stack Overflow
Udvikleren.dk: Normalisering baseret på primærnøgler