1. Feb 26

    Når skal jeg lære? Hver gang jeg leser en norsk IT-avis blir jeg like frustrert og forbannet over kommentarene som skrives. Når kom vi til det punktet der eneste kommentarene skal handle om er hvordan det er på andre plattformer eller hvordan en annen part ikke er noe bedre.

    Vi har tidligere hørt om diskusjoner rundt kvaliteten på norske IT artikler. Særlig for ITAvisen. Selv mener jeg at uansett hvor dårlig innholdet er så har det ingenting å stille opp i mot det uendelige med hjerneløse kommentarer som eksisterer.

    La oss håpe at neste gang vet jeg hvor langt jeg må scrolle for å unngå kommentar-titlene.

  2. Dec 25
    At 8 drinks, you switch the torrent from FreeBSD to Microsoft Bob.  Cmon, itll be fun!

    At 8 drinks, you switch the torrent from FreeBSD to Microsoft Bob. C'mon, it'll be fun!

    Det er alt for lite livlige bilder her i bloggen. Derfor sender jeg med dette bildet som lærer dere flow charts!

  3. Dec 24
    Lenkebrudd

    Lenkebrudd

    Dette skriveriet er løst basert på en ALA artikkel jeg leste her om dagen. Den omhandler hvordan du kan lage en feilmeldingsside som er mer informativ både til deg og brukeren som opplever den. ALA forfatteren har valgt å dele inn forskjellige error 404-meldinger i 4 grupper. Jeg derimot velger å sette disse til 3 for enkelhetens skyld.

    • Feil fra brukerens side. Gammelt bokmerke, feilskreven URL.
    • Et brudd på en lenke på din side.
    • Et brudd på en lenke fra en annen side. Enten en søkeside eller en annen side.

      Hovedsakelig ønsker vi som utvikler og eier av siden informasjon dersom det er brudd på en lenke i din side, men også muligens fra andres sider. Dersom det er noen som lenker til siden din (kanskje en annen blogg) så kan du sende en e-post til de og informere om lenkebruddet. Gammelt bokmerke eller feil skrevet URL trenger vi ikke så mye informasjon om.

      For å finne hvor brukeren kom fra kan vi bruke superglobale tabellen _SERVER og hente ut verdien av HTTP_REFERER. Det er viktig å huske at HTTP_REFERER ikke er 100% nøyaktig. Den fungerer bare dersom det blir linket igjennom en a-tag, eller igjennom form-submitt og bilde-kilde. Det fungerer altså ikke dersom det er linket igjennom en e-post, med en redirect, lasting igjennom XML, bokmerke og lignende. Det er også ganske lett å endre innholdet i HTTP_REFERER, så dersom den skal skrives ut må vi ta høyde for XSS. Siden dette ikke er en veldig essensiell funksjon vi skal lage, holder HTTP_REFERER lenge som en pekepinn på hvor brukeren kom i fra. Det er også ingen reell trussel for XSS siden vi ikke trenger å skrive ut verdien eller bruke den i en database eller lignende. HTTP_REFERER kan også ikke eksistere i enkelte tilfeller, derfor er det lurt å ta en isset()-test når man setter verdien.

      Vi setter verdien av HTTP_REFERER slik:

      $referer = null;
      if(isset($_SERVER['HTTP_REFERER'])) {
          $referer = $_SERVER['HTTP_REFERER'];
      }

      1. Gammelt bokmerke eller feilskreven URL

      Dersom $referer er null går vi ut i fra at det går under kategori 1. Vi har ingen stor nytteverdi av å vite dette i noen slags logg eller på e-post, derfor skriver vi bare ut til brukeren at de burde oppdatere bokmerkene sine, eller se etter korrekt side ved å bruke søketjenesten vi har på siden.

      echo "
      <h2>Feilmelding: 404 Fil ikke funnet!</h2>
      \n";
      echo "
       
      Filen du letet etter finnes ikke her. 
       
      ";
      if($referer === null) {
      	echo "Det ser ut til at du bruker et gammelt
      	bokmerke eller har skrevet inn feil URl.
       
      Prøv søkefeltet på siden eller skriv inn
      korrekt URL i adressefeltet i nettleseren din.\n";
      }

      Vi skriver bare ut en enkel feilmelding til brukeren, og logger ikke eller noe i den dur.

      2. Et brudd på en lenke på din side

      Dersom det er et brudd i en lenke på vår side vil vi gjerne vite om det for å kunne korrigere feilen. Derfor kan vi velge å i tillegg til å skrive ut feilmelding så logger vi hendelsen og sender en e-post til administrator om hva som har skjedd.

      Dersom vårt domenenavn er i $referer går vi ut i fra at det er en brudd i en lenke på siden vår. Det er ikke krise dersom noen har tuklet med HTTP_REFERER og lagt inn domenenavnet vårt. Det fører bare til en e-post som vi kan sjekke kjapt selv. Jeg tar en enkel test her for å vise konseptet.

      if (stristr($referer, $_SERVER['SERVER_NAME'])) {
      	sendMailError404("BROKEN_LOCAL", $referer);
      	logError404("BROKEN_LOCAL", $referer);
       
      	echo "Det ser ut til at vi har et lenkebrudd på siden
      	vår. Vi vil med dette se nærmere på saken og håper
      	å få fikset det i løpet av kort tid.
       
              Prøv søkefeltet på denne siden for å finne
      	en annen link til denne siden.\n";
      }

      Her bruker jeg to pseudo-funksjoner til å vise til hvordan en kan gjøre det. sendMailError404 sender rett og slett e-post til administrator som informerer om at det er et lenkebrudd på siden som $referer viser til. Loggen lagrer bare samme informasjon i en txt-fil på root-området eller lignende.

      3. Et brudd på en lenke fra en annen side

      Ved øvrig hendelser, hvor referer er satt men ikke inneholder domenenavnet ditt kan man gå ut i fra at det er en annen side som har en brutt lenke til siden din. Her er det kanskje ikke nødvendig å sende inn en e-post hver gang dette skjer. Ofte kan det være slik at søkesider har gamle sider indeksert og da kan det være litt plagsomt å få flere e-poster hver dag med informasjon om lenkebrudd fra f.eks Google. I dette tilfellet ville jeg bare ha logget hendelsen og med jevne mellomrom sjekket loggen etter noen lenkebrudd fra f.eks bloggrollen min eller andre sider.

      else {
      	logError404("BROKEN_EXTERNAL", $referer);
      	echo "Det ser ut til at vi har et lenkebrudd på en
      	ekstern side. Vi vil med dette se nærmere på saken og håper
      	å få fikset det i løpet av kort tid.
       
              Prøv søkefeltet på denne siden for å finne
      	en annen link til denne siden.\n";
      }

      Vi kan sette en komplett semi-kode på dette for å vise til hvordan det kan gjøres.

      $referer = null;
      if(isset($_SERVER['HTTP_REFERER'])) {
          $referer = $_SERVER['HTTP_REFERER'];
      }
       
      echo "
      <h2>Feilmelding: 404 Fil ikke funnet!</h2>
      \n";
      echo "
       
      Filen du letet etter finnes ikke her.
       
      ";
       
      if($referer === null) {
      	echo "
       
      Det ser ut til at du bruker et gammelt
      	bokmerke eller har skrevet inn feil URl.
       
      Prøv søkefeltet på siden eller skriv inn
      	korrekt URL i adressefeltet i nettleseren din.
       
      \n";
       
      } else if (stristr($referer, $_SERVER['SERVER_NAME'])) {
      	sendMailError404("BROKEN_LOCAL", $referer);
      	logError404("BROKEN_LOCAL", $referer);
       
      	echo "
       
      Det ser ut til at vi har et lenkebrudd på siden
      	vår. Vi vil med dette se nærmere på saken og håper
      	å få fikset det i løpet av kort tid.
       
      Prøv søkefeltet på denne siden for å finne
      	en annen link til denne siden.
       
      \n";
      } else {
      	logError404("BROKEN_EXTERNAL", $referer);
      	echo "
       
      Det ser ut til at vi har et lenkebrudd på en
      	ekstern side. Vi vil med dette se nærmere på saken og håper
      	å få fikset det i løpet av kort tid.
       
      Prøv søkefeltet på denne siden for å finne
      	en annen link til denne siden.
       
      \n";
      }

      Sette en PHP-fil som feilmeldingsdokument

      Når man har laget et PHP-dokument som inneholder koden over må man sette filen man lagrer det som til en Error 404 dokument. Dette gjør man i htaccess filen på følgende måte:

      ErrorDocument 404 /php/404.php

      Nå har vi en error 404 side som er mye mer informativ for både deg og brukeren. På denne måten kan vi også holde oversikt og få hjelp til å finne lenker som er brutt på andres sider som lenker til din side, eller lenker som er brutt på din egen side.

      Som alltid setter jeg pris på tilbakemeldinger.

      Ha en flott jul og et godt nytt år.

      \\ emneord: , , , ,

    1. Dec 22

      De som har prøvd tabeller/matriser i språk som f.eks Java, vet at det ikke er like enkelt og smertefritt å anvende de som i f.eks PHP. I PHP har vi uendelig mange muligheter med matriser og vi kan stort sett gjøre hva vi vil med de, uten å tenke så veldig mye på konsekvensene. Slik er det ikke med høynivåspråk som Java, C++ osv.

      Her har vi begrenset muligheter for hva vi kan gjøre og det er enda viktigere at det vi gjør burde være optimalisert og gå så kjapt som mulig. Det er da vi burde se på optimalisering av algoritmene vi gjør i programkodene.

      La oss ta et eksempel om en matrise med tall, som ofte er tilfellet. Vi skal søke igjennom matrisen, og finne på hvilken indeks vi har tallet X. For nybegynnere eller late, vil det naturlige valget være en lineær fremgangsmåte. Det vil si vi starter på indeks 0 og går til lengden på tabellen og går igjennom hver eneste indeks og ser om denne passer til argumentet vi har gitt. Denne fremgangsmåten kan være effektiv dersom vi treffer på resultatet på en av de første indeksene og stopper løkken der ved å returnere resultatet. Men hva om vi ikke har et treff før helt i slutten av tabellen? Da ville man ha brukt mye unødvendig tid på å lete igjennom N antall indekser før man traff på den siste. Det må altså være en bedre måte og gjøre dette på.

      Ta deg en 5-minutters tenkepause og prøv å tenk ut en bedre fremgangsmåte. Vi har flere måter å bruke en løkke-struktur på. Dersom vi har to nøstede løkker har vi en kvadratisk fremgangsmåte (n²), 3 nøstede løkker så er det n³ osv. Men vi har også noen bedre metoder som er raskere; det er logaritmiske fremgangsmåter. Og binærsøk, som vi skal se på nå, er en såkalt logaritmisk fremgangsmåte.

      I steden for å søke igjennom alle indekser, kunne det ikke tenke seg at det er enklere å starte med en sortert tabell og gå til medianen for å så sjekke om medianen er høyere eller lavere enn tallet vi er ute etter? På den måten har vi halvert tabellen vi leter igjennom og har mindre data å lete igjennom. Om man gjør dette igjen, ved å sette medianen av den nye tabellen, og sjekke om den er høyere eller lavere enn tallet vi er ute etter. Sånn fortsetter vi til vi har kommet frem til tallet. Siden det dataen halveres for hver iterasjon er det en logaritimisk fremgangsmåte, og det er lett å se for seg at dette er en mye mer effektiv fremgangsmåte.

      La oss se hvordan det blir utført i praksis. Vi starter med en sortert tabell som har verdiene, 2, 3, 6, 9, 12, 21, 24, 31, 33.

      Siden den er sortert kan vi se på medianen (som er den midterste verdien) 12. Dersom tallet vi leter etter, 24, er over 12 vet vi at den eksisterer et sted mellom 21 og 33 (siden den ikke er 12), eller fra indeksen 5 til 8. Allerede har vi gått fra en datamengde på 9 tall til bare 4 tall. Dersom vi gjør dette igjen vil medianen bli indeksen 6 (avrundet) og den er hverken over eller under 24, men lik. Derfor har vi indeksen vår, altså 6. Som vi ser er dette en mye mer effektiv måte å lete igjennom en tabell på. Her brukte vi 2 gjennomganger fremfor 6 som ville ha vært nødvendig i en lineær fremgangsmåte.

      Nå kan vi se på litt kode som gjør dette for oss. Du kan selv gjøre dette i ditt favorittspråk, men jeg foretrekker per dags dato Java, og vil gjøre det i dette språket.

      1
      2
      3
      4
      5
      6
      7
      8
      9
      10
      11
      12
      13
      14
      15
      16
      17
      18
      19
      20
      21
      22
      23
      
      public class BinarySearch {
          public int binarySearch (int[] heystack, int needle) {
              int low = 0;
              int high = heystack.length-1;
              int median;
       
              while (low < = high) {
                  median = (high+low)/2;
                  if(needle > heystack[median]) {
                       // Vi skal ha en større verdi, så vi halverer i lengden fra bunnen
                       low = median+1;
                  } else if (needle < heystack[median]) {
                       // Vi skal ha en mindre verdi, så vi halverer i lengden fra toppen
                       high = median-1;
                  } else {
                       // Vi sitter på verdien på medianen som er lik needle, så vi har verdien vår.
                       return median;
                  }
              }
              // Vi fant ingenting, derfor returnerer vi -1
              return -1;
          }
      }

      Dette er en måte å gjøre det på. Vi kan også gå frem på en rekursiv måte dersom vi vil unngå en løkke.

      1
      2
      3
      4
      5
      6
      7
      8
      9
      10
      11
      12
      13
      14
      15
      16
      17
      18
      19
      
      public class BinarySearch {
          public int binarySearch (int[] heystack, int needle, int low, int high) {
              // Vi har gått for langt, og vi har ingen verdi..
              if(high < low) return -1;
       
              int median = (high+low)/2;
       
              if(needle > heystack[median]) {
                   // Vi skal ha en større verdi, så vi halverer i lengden fra bunnen
                   return binarySearch(heystack, needle, median+1, high);
              } else if (needle < heystack[median]) {
                   // Vi skal ha en mindre verdi, så vi halverer i lengden fra toppen
                   return binarySearch(heystack, needle, low, median-1);
              }
       
              // Vi sitter på verdien på medianen som er lik needle, så vi har verdien vår.
              return median;
          }
      }

      Mange syns kanskje den rekursive metoden er bedre enn den iterasjonsmetoden, men for min del er itereringen like grei.

      Håper dette setter litt lys på at det finnes bedre metoder å løse en ting på en den du kanskje tenker først.

    2. Dec 06

      I feiringen av fullført datateknikk eksamen, skal jeg nå sette kunnskapene mine på en siste prøve. Jeg skal nå skriv en artikkel om bitwise-operasjoner som en gjerne bruker med et høynivåspråk som f.eks Java eller C++. Før, på en tradisjonell prosessor, ble bitwise-operasjoner gjerne brukt av en CPU i steden for addisjoner og substraksjoner. Dette er som regel ikke tilfellet nå i en CPUs mer moderne form, nå som addisjon og substraksjon er like rask som bitwise-operasjoner. 

      Først litt om hva en bit og en byte er. En bit er et siffer i en binær sammenheng. Et binært tallsystem (også kjent som 2-tallsystemet) er det som blir brukt internt av en datamaskin og all data og innhold i en maskin brytes ned til binære mønster for maskinen. Her er det kun 0 og 1 (høy spenning eller lav spenning) som duger.

      Jeg nevnte at bit var et siffer i et binært mønster. En byte (som dere kanskje kjenner igjen som en størrelsesenhet på maskinen) er en samling av slike bits. 8 bits for å være helt nøyaktig. I en byte er derfor maksimalverdien 255 i ti-tallsystemet (1111 1111 i to-tallsystemet).

      Et ord derimot er en samling av bits uten en fast størrelse. Ord er et bitmønster i en lokasjon/linje i et minne. Et ord kan derfor være på f.eks 16 bit, 32 bit, 64 bit.

      Bitwise-operasjoner

      Vi har 6 forskjellige bitwise-operasjoner.

      1. AND – &
      2. OR – |
      3. XOR – ^
      4. NOT – ~
      5. RIGHT SHIFT – >>
      6. LEFT SHIFT – <<

      (Det du ser til høyre, etter -, er tegnene som blir brukt i høynivåspråk for disse operasjonene.)

      AND

      AND blir brukt til å se hvilke bits som korresponderer i et bitmønster. Her tar jeg utgangspunkt i et mønster på lengden 8 bits, altså en byte. 

      Her tar jeg utgangspunkt i tallene 133 og 203. 133 er 1000 0101 og 203 er 1100 1011.

         // 1000 0101 & 1100 1011
         1000 0101
         1100 1011
         ------------
         1000 0001

      Som du ser resulterer det i et bitmønster som har 1 hvor det er 1 på begge bytene og 0 hvor det er ulikt eller likt på 0. 

      Dette kan du f.eks bruke til å finne om en gitt bit er satt eller ikke:

      // Denne returnerer 0 (boolsk verdi: false) da bitverdien for 2 ikke er satt.
      System.out.println(4 &amp; 0x02);

      OR

      OR blir brukt til å se hvilke to bits sammenlagt har 1. Dvs dersom en av bitene på to bitmønster har 1 vil resultatet si 1. 

      Jeg tar igjen utgangspunkt i samme tall som på AND.

         // 1000 0101 | 1100 1011
         1000 0101
         1100 1011
         ------------
         1100 1111

      Som du ser blir det 1 hvor en av bitmønstrene har 1 i seg på den plassen.

      XOR

      Denne operasjonen er en “enten eller” operasjon. Den blir 1 hvis og bare hvis de to bitene er ulike. 

      Tar fortsatt utgangspunkt i samme tall.

         // 1000 0101 ^ 1100 1011
         1000 0101
         1100 1011
         ------------
         0100 1110

      NOT

      NOT-operasjonen er en måte å finne det motsatte på. Eller du kan gjerne si at du vil finne negasjonen av mønsteret.

      Tar fortsatt utgangspunkt i samme tall som før. 

         ~1000 0101
         ------------
         0111 1010

      LEFT SHIFT

      LEFT SHIFT-operasjonen flytter alle bit-verdiene ett hakk til venstre dersom noe annet ikke er gitt. Kan også flytte flere hakk til venstre dersom nødvendig.

      Tar utgangspunkt i det første tallet gitt fra AND-operasjonen. 

         1000 0101 <<
         ------------
         0000 1010
       
         1000 0101 << 2
         ------------
         0001 0100

      RIGHT SHIFT

      Samme som forrige operasjon, bare motsatt vei. Altså til høyre.

         1000 0101 >>
         ------------
         0100 0010
       
         1000 0101 >> 2
         ------------
         0010 0001

      Noen ord til slutt

      Håper dette skriveriet kan hjelpe noen til å forstå hvordan man skal bruke bitwise-operasjoner. I alle fall hvordan de fungerer. Disse operasjonene har mange forskjellige bruksområder. For eksempel kan “shifting” brukes til å finne den mest signifikante biten i et mønster og således finne ut om verdien er negativ eller positiv. NOT kan f.eks brukes til å finne absoluttverdien av et negativt tall osv.

      \\ emneord: , , ,