Basic personligt

Daniel Brahneborgs blogg

Från Dropbox till BitTorrentSync

För ungefär två år sedan började jag använda Dropbox. Först för att få tillgång till foton som en annan person hade tagit, och därefter dels för backup av diverse källkod och dokumentation, och dels för backup av foton jag tagit med mobilen. Det är ganska skönt att slippa bråka med sladdar, FileSync-program och annat trist. Så fort mobilen hittar ett wifi tuggar den en stund, och så ligger fotot i molnet och strax därefter på lokala disken på datorn hemma.

Eftersom allting lagras i molnet, kostar det pengar om man vill synka mer än ett par GB. Man får mer utrymme när man får andra att skaffa konton, men det hjälper inte så långt. Att det har blivit dags att lämna dem blev mer aktuellt när de började scanna filerna för upphovsrättsintrång. Jag gillar inte sånt.

Hos Wil Wheaton läste jag idag om BitTorrent Sync, som lät intressant. Där fungerar saker och ting ganska annorlunda.

  • Filer skickas direkt mellan klienterna, så synkar man bara till laptopen som ligger avstängd i ryggsäcken händer exakt ingenting.
  • Varje katalog som man vill synka, lever sitt eget liv. Istället för en gemensam baskatalog för allt, kan jag synka mobilfoton till laptopen och källkod till en katalog på filservern.
  • Självklart kan jag välja om katalogen ska delas ut med skrivrättigheter eller bara läsrättigheter, om jag vill skicka innehållet till någon annan.

Binärer finns för alla relevanta plattformar här. Dokumentationen är ingen höjdare, men det finns en någorlunda komplett pdf.

För att till att börja med ta över Dropbox-katalogen på Macen krävdes följande, när binären väl var installerad och startad.

  1. På “My Sync”-fliken, klicka på “+ Add Folder”.
  2. Klicka på “Generate”, för att skapa en ny nyckel.
  3. Välj Dropboxkatalogen, och klicka på Ok.

På Linuxservern var det lite struligare. Den tar-fil som finns på nedladdningssidan innehåller en binär och en licens-fil, så det packas lämpligen upp i en temporärkatalog, och så flyttar man binären till något bra ställe. Det är en ren gui-lös server, vilket gör att man måste ha en konfigurationsfil. En sådan skapas med “btsync --dump-sample-config“. Den intressanta delen ligger under “shared_folders“. Där finns “dir“, vilket i mitt fall är Dropbox-katalogen, och “secret“, som är katalogens nyckel. För att få den, väljer man katalogen i Mac-appen, och klickar på “Info”. Då finns dels en “Full access secret”, och dels en “Read only secret”. Eftersom filer ska synkas åt båda hållen, använde jag den första. Vill man ha en enkelriktad backup används den senare.

Sedan drar man igång det hela med “btsync --config /path/till/config-filen“. Helst från /etc/rc.local, eller vad man nu har för init-system.

På mobilsidan var det lite förvirrande. Appen har två flikar, “My Sync” och “Backup”. För foton börjar man på “Backup”-sidan, klickar på ikonen för att lägga till en katalog, och letar upp sina foton. Mina fanns under “/storage/sdcard0/DCIM/100MEDIA“. Under katalognamnet syns då ett mycket irriterande “0 devices online”. Man klickar på kugghjulet, väljer “Share folder”, och får då en QR-kod som man kan scanna, eller skicka via valfri app, t.ex. som mail till sig själv.

Sedan går man tillbaka till sin desktop-app, och väljer “+ Add folder” igen. Istället för “Generate”, kopierar man nu in den kod som man nyss mailade. Med Dropbox kopierades fotona till en underkatalog till dess baskatalog, men det går inte nu. Istället valde jag en ny katalog under “Pictures”. Efter att ha klickat “Ok” får mobilen kontakt med datorn, det står “1 devices online” (för det är jättesvårt att göra en if-sats om antalet är 1), det tuggas en stund, och efter att ha klickat i “Auto-start” under “Settings”, hålls allting synkroniserat.

Vill man synka foton från två mobiler, eller som i mitt fall både från mobilen och surfplattan, måste de synkas till varsin katalog på datorn. Att byta destinationskatalog går inte, så vill man ha filerna någon annanstans måste den först tas bort, och så får man börja om från början med “Share folder”.

Det är lite mer att tänka på, och kräver lite mer planering kring vad man egentligen vill kopiera vart, men det känns helt klart som ett stort steg framåt.

April 15th, 2014 Posted by Daniel Brahneborg | blogg | 4 comments

Code review och refaktorering

Jag har ägnat mycket tid åt att göra code reviews och refaktoreringar, vilket har varit förvånansvärt lärorikt.

Som ett första steg gick jag igenom alla “char*”, för att se vilka som kunde markeras med “const”. Den delen har jag bloggat om tidigare.

Av en slump upptäckte jag en dag ett störande mönster i våra switch-satser. Det var ganska ofta som en case-gren såg ut så här:

case x:
  if (villkor) {
    // grejer
  }
  break;

Genom att ändra första raden till “if (!villkor) break;” kunde hela “grejer”-delen shiftas ut till vänster ett steg, så den inte behövde få radbrytningar lika ofta. I flera fall var de här if-satserna både långa och nästlade flera nivåer, vilket gjorde det svårt att snabbt se vad som hände. Nu ser koden mer ut så här:

case x:
  if (villkor) break;
  // grejer
  if (villkor2) break;
  // fortsätt
  break;

Tydligt och rakt på sak.
Det här var också vanligt:

case x:
  if (villkor) {
    // grejer
  } else {
    // andra grejer
  }
  break;

Genom att avsluta “grejer”-grenen med en “break” (eller “return” i vissa fall) kunde “else” försvinna, och den delen shiftas ut ett steg till vänster precis som ovan. Mer plats för den koden, och en tydligare signal att det faktiskt inte kommer hända någonting mer i “grejer”-grenen, eftersom man annars måste leta efter slutet av else-grenen. Jag blev riktigt förvånad över hur mycket högre läsbarhet det blev av det här. I ett fall så var det samma villkor i nästan alla case-grenar samt på några ställen till senare i funktionen, vilket slutade med att hela funktionen delades i två. Att originalkoden var så pass uppdelad hade jag ingen aning om innan den här omskrivningen. En bra princip var att se till att grenen med minst mängd kod kom först, så det blev “om något villkor, gör något litet, sedan hoppa härifrån”. På det sättet minimerades mängden indenterad kod.

Jag skickade hela källkoden genom “sort | uniq -c | sort -nr”, vilket visade vilka rader som var vanligast. Saker som “break” kan ju gott finnas i hur många exemplar som helst, medan komplexa uttryck helst inte ska finnas i mer än ett. Rensar man först bort inledande whitespace och måsar, samt har någorlunda konsekvent namngivning och formattering, ser man lätt eventuella störande mönster.

Det jag upptäckte ganska snart var att koden hade massor med jämförelser med NULL. I boken Code Complete rekommenderas att man jämför pekare explicit med NULL på det här sättet. Jag tycker tvärtom. Alla som har programmerat C ett tag vet att “if (ptr)” betyder samma sak som “if (ptr != NULL)”, det vill säga det testar om pekaren pekar på någonting vettigt. Att anpassa sin kod efter folk som inte kan språket den är skriven i är ungefär lika dumt som att tro att man gör sig bättre förstådd om man pratar engelska med svensk grammatik när man pratar med en spanjor. Det är mest bara plågsamt för alla.

Skillnaden i det här fallet kommer när jag läser koden. Den kompakta versionen läser jag som “om ptr pekar på någonting”. Snabbt och effektivt.

Den längre versionen kräver mer jobb. Ok, först kommer “om ptr”. Sedan en jämförelse. Kollar extra noga, och jodå, det står “skilt från”. Skilt från vad? Hmm, ser ut som NULL. Eller något annat som ser ungefär likadant ut? Nej, det är NULL. Backtrack ett steg. Ok, raden testar om ptr pekar på någonting.

Kanske överdrivet en smula, men faktiskt inte så mycket. Om man sedan behöver testa flera pekare i rad blir skillnaden ännu större. Saker som “if (source && destination)” läser jag enkelt som “om vi har både avsändare och mottagare” medan det med explicita jämförelser med NULL kanske inte längre får plats på samma rad.

Jämförelser med ‘backslash-noll-ditt-jävla-wordpress-elände-som-strippar-bort-saker-som-den-inte-ska’ rök samtidigt, av samma skäl.

Att kolla längden på en sträng med strlen kan man behöva göra ibland, men att sedan jämföra resultatet med 0 är bortom korkat. I alla fall om man använder C, men varför skulle man inte det? Det testar nämligen exakt samma sak som om första tecknet är noll. Alltså kan man skriva “ptr[0]” istället för “strlen(ptr) > 0”, vilket är både mer kompakt och effektivt. Det här syntes också när jag körde en profilering, eftersom strlen() förut tog lite större del av tiden än vad den borde.

Efter att ha likriktat en massa kod på de här sätten, insåg jag att det var ganska många kodsnuttar som fanns i flera exemplar. Samma komplexa villkor, samma två-tre rader i följd, och så vidare. Genom att refaktorera allt sådant här till nya funktioner, hittade jag enstaka ställen där något av testerna saknades, att vissa saker loggades på fel sätt, och annat smått och gott. Buggarna skulle nog aldrig inträffa ute hos kund, men det känns bra att veta att möjligheten inte längre existerar. En av de här omskrivningarna har jag också bloggat om förut.

Mitt i det här bläddrandet mellan filer hittade jag två funktioner på runt 50 rader som var identiska, förutom ett enda anrop i mitten. Jag noterade det först när jag tittade på koden med rätt perspektiv. Det var ett enkelt beslut att se till att samma kod användes i båda fallen. Det finns ett par funktioner till som också är ganska lika den här, så vidare refaktoreringar har ett tydligt fokus mot att få ihop dem helt och hållet.

Mer än någonsin känner jag mig nu övertygad om att både code review och refaktorering måste göras stegvis. Jag har nog heller aldrig förut insett hur många buggar av olika slag man kan hitta bara genom att likrikta och refaktorera kod. Nyttan i att ha testsviter som testar även väldigt enkla scenarion är också tydligare nu.

April 14th, 2014 Posted by Daniel Brahneborg | blogg | no comments

England och EU och sånt

Först så började vi kolla på Tudors, dvs England på 1500-talet. Sedan råkade vi se lite av The White Queen, men det blev lite väl mycket förvirring kring hur folket där egentligen var kopplade till folket i Tudors. Vilka var de två släkterna (i båda serierna), och varför bråkade de med varandra? Egentligen? Och hur passar Robin Hood in i allt det här? White Queen får vänta ett tag.

Via vänner och bekanta hittade jag boken “Crown and Country“, som går igenom Englands historia med början på romartiden. Släktskapen mellan folken i England, Tyskland och Frankrike reds också ut, vilket är extra kul så här i EU-tider. Det finns även fina släktträd som visar vem som har suttit på tronen från 800-talet fram tills nu. Den första personen i det trädet är kung Egbert.

Sedan började vi titta på Vikings. Vem dyker då upp helt plötsligt, om inte just Egbert! Förutom det som visas i Vikings så har jag då en rejäl backstory kring var han kom från, och vad som hände efteråt. Det pratas lite om att det för länge sedan fanns romare i England. Jag vet! Egberts (ena) son, som får några sekunder i bild då och då, fick också en son. Denna son var Albert den store, som nog är en av de coolaste typerna i Englands historia.

Samtidigt beskrivs ju vikingarna i den där boken som elaka typer som invaderade, stal tronen, och allt möjligt annat jobbigt. Det är väldigt skoj att se hela historien när vikingarna på riktigt börjar intressera sig för England, fast från det andra hållet.

En rundtur runt den där ön ligger högt på önskelistan, för att få se alla ställen i verkligheten. Det är underligt nog ont om drakar, men annars spöar det här det mesta i antal intriger och mord. Galet land. Så stora ambitioner, så mycket maktkamp. Ledarskap på elitnivå. Inspirerande som satan.

I dagens Sverige skrivs knappt en rad om valet till någonting som står för två tredjedelar av våra lagar, och till det andra valet är det ingen som vill någonting mer än att säga att den andra falangen av socialmoderaterna är dumma. Skillnaden är helt bisarr.

April 13th, 2014 Posted by Daniel Brahneborg | blogg | no comments

|