Archive for the ‘programming’ Category

Tre antipatterns i webinteraktionsdesign

Sunday, March 22nd, 2009

Ett antipattern är ett sätt att göra något på, som vid första anblicken verkar vara en vettig approach, men som egentligen gör saker värre. Inom webbutvecklingsvärlden finns det en rik flora av dessa. Här är några exempel:

Pagers som visar ett löjligt litet antal saker åt gången
En pager är alltså den gränssnittskonstruktion som visar ett visst antal saker åt gången – exempelvis sökträffar eller bloggkommentarer. Eftersom det är mycket bökigare att konstruera ett pagingsystem än att helt enkelt visa alla saker på en gång vill folk förstås använda det, och sätter därför gränsen för antal saker som ska visas alldeles för lågt. Bredband är billigt, och moderna webbläsare klarar numera sidor över 15 kb. Minst 100 saker åt gången, tack.
För korta sessionstimeouts
Alla moderna webbprogrammeringsramverk har någon typ av sessionshanteringssystem, så att programeraren ska kunna spara ner en massa information om vad en viss användare gör i steg 1, så att man kan läsa upp det igen i steg 2. Att spara denna information tar förstås lite minne i webbserverprocessen, och har man många användare vill man förstås se till att rensa bort sådant som aldrig kommer användas, eftersom användaren lämnat webbplatsen och inte kommer göra något steg 2-request. Så alla webbprogrammeringsramverk har en sessionstimeout – om inte användaren begär en ny sida på x minuter rensas den data som associerats med användaren. Och eftersom minne var dyrt under förra årtusendet är denna timeout vanligtvis löjligt lågt satt. Vilket får till effekt att den som skickar in ett långt och genomarbetat webbforuminlägg upptäcker att sessionen timat ut, och att de senaste 21 minuternas arbete gått upp i rök. Minne är billigt, men användares tid är det inte. Sätt upp sessionstimeouten till minst 24 timmar, tack.
Reset-knappar på formulär
HTML-standardens avsnitt om hur man gör formulär innehåller ett antal olika typer av formulärelement – textfält, radioknappar, selectmenyer, submit-knappar samt, av någon outgrundlig anledning, en knapp som tar bort allt man mödosamt skrivit in i formuläret, och återställer det till sitt ursprungstillstånd. Risken för att råka klicka på denna knapp är visserligen inte stor, men det lär ändå inträffa mångdubbelt fler gånger än att någon faktiskt har nytta av det. Det första exemplet i standarden använder denna vansinniga funktion, vilket får till effekt att folk som inte tänker efter tror att det är en bra idé att ge användaren tillgång till något som bara kan användas till att skjuta sig i foten. Sluta med det, tack.

Mediawiki som datalager

Monday, January 26th, 2009

lagen.nu använder jag ingen relationsdatabas. Alla dokument ligger i varsin statisk fil, och den samling av metadata som behövs för att jag ska kunna exempelvis skapa index över alla dokument ligger i en gigantisk .n3-fil som jag går igenom med RDFLib. Anledningen är förstås min djupt kända misstro mot konceptet databasserver i allmänhet och relationsdatabaser i synnerhet. Jag tycker filsystemet är underskattat som databas. Det finns alltid där, är snabbt, går att debugga och manipulera med välbekanta verktyg (ls, find, grep, xargs, tar, rsync), har ett begripligt rättighetssystem integrerat med operativsystemet, osv.

Till nästa stora iteration av lagen.nu-koden kommer jag ändå att börja använda någon sorts server för datalagring. Men det blir förmodligen inte en traditionell relationsdatabas med SQL-gränssnitt. Min datamodell är inte särskilt relationell. Med tanke på hur djupt jag integrerat RDF i systemet blir det förmodligen en kombination av en triplestore tillsammans med någon form av dokumentdatabas. För det tidigare blir det förmodligen Sesame, för det senare har jag tittat nyfiket på CouchDB.

Men i kommentarerna till ett tidigare inlägg om en mediaövervakningsbot föreslog Peter Krantz att använda Mediawiki som datalagring. Jag började kolla på hur man kan automatisera hämtning och lagring av data från en Mediawikiserver, och det visar sig att det finns en mycket kompetent pythonmodul, mwclient, för ändamålet (det finns även ett annat ramverk, pywikipedia, men det gav inte alls ett lika bra första intryck). Så här enkelt är det att skapa och ändra en sida:

    import mwclient
    
    site = mwclient.Site('www.example.org','/path/to/mediawiki/')
    site.login('myuser','secret')
    page = site.Pages['Testpage']
    page.save("Hello world", summary="initial version")
    page.save("Goodbye world", summary="updated version")
    print "Page has %d revisions" % len(page.revisions())

Allt det som mediawiki ger — revisionshantering med diffar, användarhantering, admin- och slutanvändargränssnitt, spamkontroller, roll- och rättighetssystem, och utökningsmöjligheter – får man på köpet. Det är kanske inget man vill använda för att hantera jättemånga updateringar i sekunden, men om man kan se till att exv cachea de anrop som bara hämtar data kan man nog få det snabbt nog.

Lagen 1.5 rycker närmare

Thursday, September 4th, 2008

I natt pushade jag ut en ny uppdatering av lagen.nu 1.5-betan — ta gärna en titt och säg vad ni tycker! Det är inga radikala förändringar sen sist, men lite grafisk puts med bland annat en snyggare vinjett och ett konsekvent sepiatema. För att uppmuntra feedback har även alla sidor ett formulär för felanmälan, som postar tickets rakt in i den utvecklings-trac jag använder.

Nästa steg är att skapa en epostlista för de som är intresserade av att följa, påverka och kanske delta i lagen.nu-utvecklingen. Har du varit i kontakt med mig tidigare angånde tjänsten kommer du säkert få ett mail när den är igång, hör av dig annars!

Destroy, erase, improve

Monday, August 25th, 2008

Nu har det varit tyst här ett tag igen. Jag har ägnat sommaren åt extrajobb, studier inför tentan i C4, samt jobb på nästa version av lagen.nu, som nu börjar närma sig “färdig”-stadiet. På ferenda.lagen.nu finns en betaversion av siten, och de utåt sett viktigaste nyheterna är att formgivningen är fräshare, samt att rättsfallsreferaten nu finns med i fulltext.

Men den stora nyheten bakom kulisserna är att kodbasen till 90% är helt omskriven, och att den nu är öppen källkod under BSD-licensen. Det har tagit lång tid – betydligt längre än det tog att utveckla den ursprungliga versionen – och frågan som inställer sig är om det verkligen var en sån lysande idé? Det finns två förhållningssätt till att slänga gammal kod och skriva om den från scratch — Joel säger att det är en av sakerna you never should do, medans Fred menar att man ska plan to throw one away; you will, anyhow.

De flesta utvecklares första impuls när de sitter med en kodbas som vuxit till en ogenomtränglig röra är att slänga skiten och starta om. Det är för det mesta en dålig idé, inte minst för att det inte finns någon garanti för att man inte hamnar i samma sits tre år senare, när man är klar. Men eftersom det är mycket roligare att bygga nytt än att reparera gammalt skrivs ofta system om från scratch, trots att det skulle varit mycket billigare att steg för steg rensa i det gamla röriga systemet.

Så varför skrev jag då om koden? På grund av glädje och skam. Glädje, eftersom lagen.nu inte har någon affärsplan, några inkomster ellern några krav på företagekonomiskt rationell styrning. Det är ett hobbyprojekt som jag sysslar med för att det är kul, och det har varit mycket roligare att skriva nytt än att rota runt i den gamla koden. Skam, för att det hela tiden har varit meningen att släppa koden fri, och den gamla koden var helt enkelt för dålig för att visa för folk. En kompis har teorin att det här är anledningen till att inte mer kod är öppen — det är helt enkelt för pinsamt.

Beslutet att släppa koden fri, tillsammans med en viss andra systemet-effekt, har gjort att jag i varje steg i utvecklingen har funderat kring det bästa sättet att göra en viss sak. För att slippa skämmas måste man helt enkelt skriva så bra kod som man någonsin kan. När jag skrev det första systemet var jag ganska grön på python, och försökte mest komma på något sätt att göra samma sak. Det tar mycket mer tid att göra rätt än att göra snabbt — särskilt i början – men känslan av yrkesstolthet gör att det är värt det.

Det betyder inte att det inte finns en massa fulheter i koden. Jag är inte superstrukturerad, och inte min kod heller. När jag kommit på ett visst mönster för att göra saker överanvänder jag det gärna, fram till att jag kommer på nästa mönster. Och namngivning samt övrig kodstandard ska vi inte prata om. Men grunden är stabil. Arkitekturen är ganska enkel att förklara, även om det är många (drygt 9000) rader kod. Jag tror att en ny programmerare kan sätta sig in i det hela ganska snabbt, och att det kan vara ett ganska kul system att vara med och bygga på.

Dagens patch

Saturday, June 14th, 2008

Det blir mycket RDF i lagen.nu 1.5. Och det blir mycket användande av RDFLib. Efter att ha hittat finfina instruktioner om hur man får biblioteket – inklusive SPARQL-parser – att snurra under windows har jag gett mig på min pet peeve i n3-serialiseringskoden, nämligen dess ovana att definera egna anonyma namespaceprefix. Normalt serialiserar den nämligen n3-formatet något i stil med såhär:

@prefix _8: http://lagen.nu/.
@prefix _9: http://lagen.nu/1962:700#.
@prefix dct: http://dublincore.org/documents/dcmi-terms/.
@prefix rinfo: http://rinfo.lagrummet.se/taxo/2007/09/rinfo/pub#.

_8:NJA_2005_s_878 dct:identifier "NJA 2005 s. 878 (NJA 2005:95)";
rinfo:lagrum _9:K29P7;
rinfo:rattsfallshanvisning _8:NJA_1996_s_63,
_8:NJA_2000_s_421;

Men nu blir det det oändligt mycket mer läsbara:

@prefix dct: http://dublincore.org/documents/dcmi-terms/.
@prefix rinfo: http://rinfo.lagrummet.se/taxo/2007/09/rinfo/pub#.

 <http://lagen.nu/NJA_2005_s_878> dct:identifier "NJA 2005 s. 878 (NJA 2005:95)";
     rinfo:lagrum <http://lagen.nu/1962:700#K29P7>;
     rinfo:rattsfallshanvisning <http://lagen.nu/NJA_1996_s_63>,
         <http://lagen.nu/NJA_2000_s_421>;

Här är patchen:

C:\Users\staffan\tmp\rdflib-2.4.0\rdflib>diff -u syntax\NamespaceManager.py~ syntax\NamespaceManager.py
--- syntax\NamespaceManager.py~ 2007-04-04 22:05:32.000000000 +0200
+++ syntax\NamespaceManager.py  2008-06-14 21:36:32.606307200 +0200
@@ -59,8 +59,7 @@
namespace = URIRef(namespace)
prefix = self.store.prefix(namespace)
if prefix is None:
-                prefix = "_%s" % len(list(self.store.namespaces()))
-                self.bind(prefix, namespace)
+                raise Exception("Prefix for %s not bound" % namespace)
self.__cache[uri] = (prefix, namespace, name)
return self.__cache[uri]

Den som förstår RDFLib bättre kan säkert få till samma effekt utan att patcha källkoden genom att subklassa NamespaceManager och trycka in den i kedjan någonstans, men mina försök till det misslyckades.

Dagens bugg

Monday, January 14th, 2008

Följande kod, djupt nere i innanmätet på lagen.nu 1.0-koden, har en bugg, som stått orättad i över tre år (det den ska göra är att stoppa in ett ‘|’-tecken innan ändelser i stil med ‘lagen’, ‘balken’, osv — dvs ‘upphovsrättslagen’ ska bli ‘upphovsrätts|lagen’ — detta av EBNF-tekniska skäl.

fixedindata = re.sub(r'\B(lagens?|balkens?|förordningens?)\b',
                     r'|\1', self.indata)

Hittar ni felet? Ledtråd — det uppträder bara för en av de tio balkarna, samt för ett mycket litet fåtal lagar och förordningar.

XHTML2, CSS3 och PDF

Friday, December 21st, 2007

Tidigare frågade jag runt vilket som var det bästa sättet att skapa PDF från nån typ av strukturerad XML-data. De svar jag fick från olika håll pekade på att köra det gen om en CSS3-kapabel layoutmotor vore lämpligt. Så jag har ägnat lite tid åt att trimma in ett stylesheet anpassat för lagtext uttryckt XHTML2 tillsammans med metadata från ESFR-vokabulären.

Som testobjekt använde jag den lagtext som utgör kursfordran för förvaltningsrätt, dvs den kurs jag läser för närvarande. Tidigare har ett förlag tryckt upp en särskild författningssamling för detta ämne, men på introduktionsföreläsningen nämndes att detta inte skulle göras i år, då kostnaden för att ta fram uppdaterade tryckorginal för varje kursstart var för stor (kursen går två gånger om året).

Nu har jag ett automatiserat publiceringsflöde, som utgående från en huvudfil, uttryckt i XHTML2, och en samling lagtexter, också uttryckt i XHTML2, genererar en sammmanslagen fil. Denna innehåller alla författningar (eller delar därav) som huvudfilen hänvisar till genom XInclude/XPointer. Från den sammanslagna filen och ett CSS3-stylesheet skapas sen en PDF. Första steget görs med xmllint --xinclude, andra med Prince. Kostnad för att ta fram uppdaterade tryckoriginal: i princip noll.

Resultat: enkelspaltig (css), dubbelspaltig (css).

Några saker att lägga märke till:

  • Innehållsförteckningen har korrekta sidnummerhänvisningar
  • Sidhuvudet visar var och i vilken lag man befinner sig på (och växlar utseende beroende på om det är en kapitelindelad lag eller inte)
  • Huvudfilen anger vilka förkortningar som ska användas för aktuell lag i sidhuvudet
  • Höger- och vänstersidor ser olika ut (precis som i riktiga böcker!)
  • Avstavning sker automatiskt efter svenska regler
  • PDF-bokmärkena ger en hierarkisk översikt över hela filen
  • Det går att inkludera bara enstaka kapitel (eller andra avsnitt) från en lag

Det finns förstås mycket kvar att fixa (kolla exv SekrL 16 kap - inte många rätt i formatteringen där), och även mer att skriva om hur man kan använda CSS3 och Prince XML, men det får bli efter julen.

Tablet PC:s, studieteknologi och PDF-byggande

Friday, December 7th, 2007

Sedan någon månad tillbaka använder jag min Tablet PC som studiehjälpmedel i kursen förvaltningsrätt. Mitt huvudsakliga verktyg för antecknande är Evernote, som håller reda på en samling anteckningar i både och maskin- och handskrivet format, och organiserar dem med taggar (tyvärr dock ingen svensk handstilsigenkänning). På föreläsningar där jag är en student bland hundra använder jag datorn som en vanlig laptop och skriver på tangentbordet, men på mindre seminarier och lektioner där interaktivitet och diskussion förekommer använder jag den i tabletläge och skriver på skärmen, för att inte gömma mig bakom en uppfälld skärm.

Istället för en lagbok använder jag en PDF-fil som jag skapat med betalversionen av Adobe Acrobat, som vi har på jobbet. Den antecknar jag sedan i med PDF Annotator, både i tablet- och laptopläge, och har numera en någorlunda genomklottrad fil. Tyvärr får jag inte ta med mig datorn på tentan, så dagarna innan har jag tänkt överföra de understrykningar (men inga anteckningar)

Jag tycker det här sättet att jobba på funkar riktigt bra. Om kurslitteraturen fanns att köpa elektroniskt skulle datorn vara det enda jag behövde släpa på till och från skolan. Men det finns några problem utöver att jag måste övergå till amishteknik inför tentan, varav det största är att lagtext-PDF:en är undermålig. Det vore ju mycket bättre om lagen.nu hade nån sorts “generera författningssamling i PDF-form”-funktion. Jag ser fyra sätt att bygga en sådan, givet källmaterial är i XHTML2 och RDFa och följande krav:

  • Automatisk avstavning som följer svenska regler
  • Kontroll över sidfötter och huvuden som automatiskt reflekterar vilken lag och vilka paragrafer som finns på varje sida (tänk sidhuvuden i typisk telefonkatalog eller lexikon)
  • Automatisk generering av innehållsförteckning och index
  • Fungerande interna och externa hyperlänkar i resultatet
  • Kontroll över generering av PDF-bookmarks
  • Andra saker som blir uppenbara när en lösning som saknar dem står färdig.

Jag kan se fyra sätt:

  1. Old school: Transformera XHTML2-koden till (La)TeX och låt pdftex bygga en snygg PDF
    + Snygg typografi, riktigt bra svensk avstavning
    – Jag och (La)TeX har, trots upprepade försök, inte bondat riktigt
  2. New school: Transformera XML-koden till XSL-FO och låt fop eller någon annan processor göra PDF av det hela
    + Standardiserat och fint
    – Jag kan inte XSL-FO. Finns det nån gratis XSL-FO -> PDF-processor som är bra?
  3. Bleeding edge: Skriv ett superavancerat CSS3-stylesheet, koppla direkt mot XHTML2-datat och koppla in en CSS3-kapabel PDF-genererare
    + Ingen mellantransformering
    – Jag kan inte CSS3 (och är djupt misstänksam mot tidigare CSS-varianter). Prince XML är svindyrt.
  4. NIH-syndromet: Använd iText eller annat lib för att generera PDF direkt.
    + Jag slipper bli expert på ett sidbeskrivningsspråk
    – Jag måste bli expert på ett API

Dear lazyweb: vad skulle ni välja (givet att ni inte är experter på LaTeX, XSL-FO eller CSS3)?

“För mycket kunskap är en tung börda”

Wednesday, September 20th, 2006

Ovanstående citat är antingen det mest korkade eller det mest insiktsfulla jag kläckt ur mig på länge. Det jag tänkte på var att hur komplext ett område kan kännas när man lärt sig mycket om det, och mer specifikt var det i kontexten av mitt eget efterforskande kring legalt skydd för tekniska skyddsåtgärder.

Samtidigt diskuterade jag Unicode idag, ett ämne av ungefär samma komplexitet, där det känns som jag kommit över backkrönet och hittat the zen of unicode. Resan har varit ungefär såhär:

I början: “Om man använder typ WideCharToMultiByte för att spara som UTF-8 så funkar det med alla tecken”

I mitten: “Fast UTF-8 löser bara transportproblemet och får inte förväxlas med riktiga strängar, samt att man måste räkna med att bytearrayn kan bli sex gånger så lång som antalet bokstäver, och så måste man tänka på att en 16-bitars widechar bara kan representera Basic multilingual plane och unicodedatabasen är för stor att ha i möblerade rum och att om man ska jämföra strängar så måste man se till att de är normaliserade först och tänk på att Ruby inte har unicodesträngar eftersom japaner i allmänhet tycker att det där med Han unification är ett problem och även om Tengwar kanske kommer med i nästa version så finns det nog inte glyfer i din font för det och…. GAAAAAH, ge mig swascii istället!”

I slutet: “Det finns codepoints i NFC. Allt annat är bara skuggor på väggarna

Nu har jag iofs lärt mig mindre om Unicode än vad någon som Tim Bray har hunnit glömma bort, men just nu känns det som komplexiteten på det området är borta — alla bollarna som var i luften har nu landat, och jag kan lösa alla teckenuppsättningsproblem som kommer i min väg (FLW…). Och det var väl det som var poängen — innan man kommer över krönet är kunskapen en tung börda (jfr “ju mer man vet, desto mer förstår man hur mycket man inte vet”).

Så, för att jämföra med min insikt i skydd för tekniska skyddsåtgärder:

I början: “Man får typ inte knäcka kopieringsskydd längre för det har WIPO bestämt

I mitten: “Fast frågan är vad som är en effektiv teknisk åtgärd i lagens mening, med tanke på att en teknisk åtgärd aldrig kan vara 100% effektiv i teknisk mening, och innebär det faktum att temporära kopior är upphovsrättsligt relevanta och kräver upphovsrättsinnehavarens samtycke att det har uppstått en de facto åtkomsträttighet vid sidan av exemplarframställningsrättigheter och spridningsrättigheter, och är det i så fall en del av upphovsrätten eller är det fråga om paracopyright, och vad innebär artikel 11:s begränsning till “their rights under this treaty” för möjligheten att kringgå tekniska åtgärder inom ramen för upphovsrättsinskränkningarna och varför är listan i infosoc artikel 6(4) 4 st. över inskränkningar som kan ges företräde bara tillämpliga på fysiska exemplar och varför är förbudet mot kringgåendeverktyg kopplat till att det ska finnas en ekonomisk marknad för legala användningsområden och… GAAAAH, skriv om upphovsrättslagen i Prolog istället!”

I slutet: … jag vet inte riktigt. Jag hoppas på att hitta the zen of skydd för tekniska åtgärder innan den 3:e oktober. Vi får väl se hur det går.