Poster taggade med ‘länkar’

Sida 1 av 212

Idag tillhör det vanligheterna att du som utvecklare skriver automatiska test för din kod. Många projekt använder sig av olika former av dependency injection eller har beroenden mellan klasser som gör det krångligt att testa varje del för sig. Detta leder ibland till att tester omfattar stora delar att systemet (mer åt integrationstestning), vilket i sin tur leder till att det blir krångligt att underhålla och svårt att felsöka. Vissa framhåller att större tester gör dem robusta – de går inte ”sönder” lika lätt om något ändras inne i implementationen – men jag föredrar en robust implementation framför ett robust test, om ni förstår vad jag menar. Ju mindre del som varje test måste verifiera desto bättre – själva grunden för enhetstestning.

Hur bryter du isär koden så att det går att testa separat då? Jo, här kommer då mockobjekt in i bilden. Med hjälp av dessa syntetiska objekt som representerar dina kodberoenden så kan du isolera den kod som du vill testa, utan att råka ut för NullPointerException. Termen myntades (iallafall för den bredare publiken) av några utvecklare på en extreme-programming-konferens år 2000, där de också presenterade ett första ramverk för detta.

Ponera följande kodexempel (där Courier är ett interface)

class AwesomeApp {
   Courier courier;
   public Content checkPacket() {
      if ( !courier.hasNewPacket() ) {
         throw new NoNewPacketAsFarAsWeCouldSeeException();
      }
      Packet packet = courier.getNewPacket();
      Content content = packet.open();
      return content;
   }
   public void setCourier(Courier courier) {
      this.courier = courier;
   }
}

Om jag skriver följande test, så ramlar jag oundvikligen ned i NullPointerException-gropen eftersom courier är null i AwesomeApp.

class AwesomeAppTest {
   public void testCheckPacket() {
     AwesomeApp app = new AwesomeApp();
     Content content = app.checkPacket();
     // Assert content
   }
}

Vad göra? Lösningen är då alltså att använda ett mockobjekt. Antingen kan jag skriva en egen klass som implementerar interfacet Courier, samt hantera alla testvillkor som objekt av den klassen måste uppfylla, eller så använder jag ett färdigt ramverk. Valet känns lätt. Genom att välja ett färdigt ramverk så slipper jag en del underhåll och får samtidigt ett färdigt utvecklingsmönster att följa – annars kan det lätt bli att varje utvecklare i ett projekt gör på sitt eget sätt.

De vanligaste ramverken som används idag skulle jag säga är EasyMock, JMock samt Mockito. De är alla likvärdiga i funktionalitet och även om konstruktionerna kan skilja sig lite åt så är grunden densamma. Jag har också stött på ett ramverk som heter RMock, men det är gammalt och stöder inte ens Java 5 Generics, så jag tar inte upp det här. Här nedan följer några exempel på hur AwesomeAppTest skulle skrivas med alla tre ramverken, så att läsaren kan jämföra.

JMock

JMock har funnits länge och är en vidareutveckling av det ramverk som presenterades på extreme-programming-konferensen jag nämnde ovan. Version 1 var lite knölig att använda, eftersom metodmatchning gjordes med strängar vilket gav problem vid refaktorisering. Detta är dock löst i version 2 som sedan länge är den som gäller.

class AwesomeAppTest {
   @Test
   public void testCheckPacket() {
      // JMock-specifik klass
      Mockery mockery = new Mockery();
      // Här skapar vi vårt mockobjekt med JMock
      Courier courier = mockery.mock(Courier.class);

      // Förväntat returvärde från testade koden
      Content expectedContent = new Content();
      // Returvärden från mitt mockobjekt
      Packet anyPacket = new Packet(expectedContent);

      // Definiera våra förväntningar, ett anrop till
      // courier.hasNewPacket() och ett till
      // courier.getNewPacket() samt deras returvärden
      mockery.checking(new Expectations() {{

         oneOf(courier).hasNewPacket();
         will(returnValue(true));

         oneOf(courier).getNewPacket();
         will(returnValue(anyPacket));

      }});

      AwesomeApp app = new AwesomeApp();
      // Här sätter vi vårt mockobjekt som
      // beroende till AwesomeApp
      app.setCourier(courier);
      Content content = app.checkPacket();

      // Kontrollera att resultatet är det förväntade
      assert content == expectedContent;

      // Verifiera att förväntningarna inträffade
      mockery.assertIsSatisfied();

   }
}

EasyMock

EasyMock är också ganska gammal i gemet och var tidig med att ha stöd för refaktorisering.

class AwesomeAppTest {
   @Test
   public void testCheckPacket() {
      // Här skapar vi vårt mockobjekt med hjälp av EasyMock
      Courier courier = EasyMock.createMock(Courier.class);

      // Förväntat returvärde från testade koden
      Content expectedContent = new Content();
      // Returvärden från mitt mockobjekt
      Packet anyPacket = new Packet(expectedContent);

      // Definiera våra förväntningar, ett anrop till
      // courier.hasNewPacket() och ett till
      // courier.getNewPacket()  samt deras returvärden
      EasyMock.expect(courier.hasNewPacket()).andReturn(true);
      EasyMock.expect(courier.getNewPacket()).andReturn(anyPacket);

      // Sätt EasyMock i replay-läge,
      // där förväntningarna skall uppfyllas
      EasyMock.replay(courier);

      AwesomeApp app = new AwesomeApp();
      // Här sätter vi vårt mockobjekt som
      // beroende till AwesomeApp
      app.setCourier(courier);
      Content content = app.checkPacket();

      // Kontrollera att resultatet är det förväntade
      assert content == expectedContent;

      // Verifiera att förväntningarna inträffade
      EasyMock.verify(courier);
   }
}

Mockito

Mockito är i praktiken en vidareutveckling av EasyMock, från början en fork som nu har skrivits om helt. Tack vare arvet är dock syntaxen väldigt lik.

class AwesomeAppTest {
   @Test
   public void testCheckPacket() {
      // Här skapar vi vårt mockobjekt med hjälp av Mockito
      Courier courier = Mockito.mock(Courier.class);

      // Förväntat returvärde från testade koden
      Content expectedContent = new Content();
      // Returvärden från mitt mockobjekt
      Packet anyPacket = new Packet(expectedContent);

      // Definiera våra förväntningar, ett anrop till
      // courier.hasNewPacket() och ett till
      // courier.getNewPacket() samt deras returvärden
      Mockito.when(courier.hasNewPacket()).thenReturn(true);
      Mockito.when(courier.getNewPacket()).thenReturn(anyPacket);

      AwesomeApp app = new AwesomeApp();
      // Här sätter vi vårt mockobjekt som
      // beroende till AwesomeApp
      app.setCourier(courier);
      Content content = app.checkPacket();

      // Kontrollera att resultatet är det förväntade
      assert content == expectedContent;

      // Verifiera att förväntningarna inträffade
      Mockito.verify(courier);
   }
}

Summering

Som ni ser skiljer det inte mycket mellan ramverken, det som kanske framträder mest är att EasyMock har ett steg extra – där EasyMock sätts i ”replay”-läge – mot både JMock och Mockito. Alla tre har stöd för att verifiera att metodanrop sker i rätt ordning, verifiera argument etc. Det går också att sätta mjukare förväntningar, såsom att en metod skall anropas en eller flera gånger, att man inte bryr sig om anrop och returvärde på ett visst objekt osv.

Vilket ramverk du skall välja är mer upp till personlig smak än funktionalitet. I de flesta fall kanske du sitter i ett projekt som redan använder ett mockramverk och då har du förhoppningsvis fått en lite bättre förståelse för vad ramverket gör.

Som avslutning kan jag rekommendera lite läsning från utvecklarna som myntade begreppet mockobjekt. Du hittar det på www.mockobjects.com – läs gärna deras papper som ligger som länkar i högerkolumnen på den sidan.

Nu är det återigen kortvecka och sommarstämningen börjar märkas av ordentligt. Trots det händer det massvis på kontoret!

Veckans viktigaste nyhet är att hemmabioanläggningen på kontoret är fixad – i princip… Bild och ljud fungerar samtidigt för första gången sedan Elton ”lillankan” Hedström var här och trixade för några månader sedan :-) Obs att subwoofern dock fortfarande är trasig och är inlämnad för lagning.

En annan rolig nyhet är att vi fortfarande ligger högst på Google-sökningen Stockholms bästa konsultbolag och det beror så klart på att vi har Stockholms bästa konsulter. En annan framgångsfaktor är att vi gör roliga saker tillsammans för att ”bygga laget”. Nu är det ju inte så många aktiviteter under sommaren – den enda aktivitet som står på agendan (som jag känner till) är Pollux-frukosten den 7/7. Annars så drar det hela igång igen i augusti med Midnattsloppet den 13/8 och after work på kontoret den 18/8. Höstterminens preliminära schema ser ut så här:

  • 2011-08-13: Midnattsloppet
  • 2011-08-18: After work på kontoret
  • 2011-08-27: Bellmanstafetten
  • 2011-09-09: Höstkickoff med övernattning
  • 2011-09-28: Konsultmöte
  • 2011-10-20: Konsultmöte
  • 2011-11-09: Konsultmöte
  • 2011-12-01: Konsultmöte
  • 2011-12-16: Julmiddag

Utöver detta kommer vi så klart att sockra detta med fler After Works, frukostar och Cygniluncher.

Vår nya sajt cygni.se innehåller ju en mängd olika informationsflöden för att hålla sajten levande. Stacktrace, jobbannonser och pressmeddelanden har vi ju haft tidigare men Cygnibloggen är ett nytt flöde som visar lite vad som händer här på kontoret. Jag har nu även lagt till ytterligare ett flöde som kallas Läst på Cygni som innehåller länkar till olika tekniska artiklar som vi Cygnianer läst. Jag har beskrivit hur detta fungerar tidigare men kort så går det hela ut på att bookmarka/tagga intressanta artiklar via Delicious och sen fixar Twitterfeed, Twitter och WordPress-plugins resten.

Beläggningen inför hösten börjar se riktigt bra ut nu – vi har konkreta säljhugg på i stort sett alla som kommer loss under augusti/september. Mikael Thorsson blev idag klar för Aftonbladet och börjar där 5/9. Under denna och nästa vecka är det intervjuer på ett stort spelbolag samt för en av Sveriges största sajter. Spelbolaget har redan bestämt sig för att ta in Patrik Brännström som exekverade en bländande intervju idag så han börjar där 1/9 efter sin föräldraledighet. Den stora svenska sajten känns också superkul eftersom de verkar driva roliga och utmanande projekt som nog passar oss perfekt.

Jag har lagt ut en rekryteringsannons på LinkedIn för att testa lite nya rekryteringskanaler. Jag kommer dessutom att börja jobba med ett par nya rekryteringsfirmor för att se ifall vi kan hitta potentiella Cygnianer. Det känns som att vi kommer att ha bra sprutt på rekryteringen inför hösten.

Hoppas att ni får en härlig midsommar. Själv drar jag otippat nog till Göteborg och har Googlat upp lite GBG-fakta. I fotbollslaget IFK Göteborg fanns 1982 inte mindre än fyra Glenn: Glenn Hysén, Glenn Strömberg, Glenn Schiller och Glenn Holm.

IFK Göteborg 1982
Den omedelbara frågan som poppar upp då är naturligtvis vad som händer om Glenn Hysén gifter sig med Glenn Close :-)

Vi försöker hålla vår sajt levande genom kontinuerligt fylla på sajtens innehåll via olika informationsflöden. Våra nuvarande flöden inkluderar:

  • Stacktrace: vår gemensamma teknikblogg där vi skriver allt från korta tips till längre artiklar
  • Cygnibloggen: här kan du läsa om vad som hänt på Cygnis konsultmöten, senaste nytt från Cygnis kontor och reflektioner från ledningen
  • Pressmeddelanden: officiella nyheter om nya kunder, ramavtal och liknande
  • Jobbannonser: här postar vi kontinuerligt nya jobb och karriärsmöjligheter på Cygni

Twitterintegration
Idag så fyller vi på med ett nytt informationsflöde som vi kallar Läst på Cygni. Det innehåller länkar till olika artiklar som konsulterna på Cygni läst den senaste tiden.

Några av våra konsulter driver detta flöde genom att skapa bokmärken för intressanta artiklar via Delicious och tagga dem med en speciell tagg. Delicious erbjuder automatiskt ett RSS-flöde för varje sådan tagg och detta flöde läser vi in via online-tjänsten Twitterfeed för att sedan pumpa allt vidare till twitter.com/cygniab och paper.li/cygniab. Eftersom cygni.se är en WordPress-sajt så finns ett otal integrationer färdiga mot Twitter så innehållet från twitter.com/cygniab behövde bara CSS:as för att det skulle passa bra med det övriga innehållet.

Så… kolla gärna in detta informationsflöde som visas på flera av våra sidor här på cygni.se, följ oss på twitter.com/cygniab eller läs vår tidning på paper.li/cygniab! Diagrammet till höger som är genererat via yUML illustrerar flödet grafiskt för den intresserade.

Grunden i varje webbprojekt består av en databas. I de flesta fall rör det sig om en klassisk relationsdatabas i form av MySQL eller motsvarande. Denna arkitektur är välkänd, mogen och har tjänat oss väl, men på senaste tiden har uttrycket ”NoSQL” hörts mer och mer. Bakom uttrycket döljer sig en rad olika typer av databaser som bygger på andra paradigm än den klassiska relationsdatabasen, i denna artikel tänker jag ge en översikt av dokumentdatabasen CouchDB. Läs mer >>

Detta inlägg ingår i serien Spring från början och kommer att behandla det transaktionsstöd som finns i springmodulen spring-tx.

Transaktioner är ett sätt att hålla ihop en eller flera operationer. Typiskt gäller principen ”allt eller inget” vilket betyder att alla operationer som ingår i en transaktion ska exekveras utan fel för att transaktionen ska gälla. Det vanligaste fallet är databastransaktioner där exempelvis flera skrivningar måste exekveras utan fel innan en så kallad commit genomförs. Ett exempel på detta är det klassiska bankkontoexemplet med överflyttning av pengar från ett konto till ett annat. En överflyttning sker genom att ett uttag först sker från ett konto och sedan insättning på ett annat konto. Bägge operationerna måste lyckas, annars ska transaktionen inte gälla det vill säga att man ”rullar tillbaka” transaktionen via en så kallad rollback.

Spring erbjuder på ett enhetligt sätt stöd för att kunna hantera transaktioner av olika slag som till exempel JTA, JDBC, Hibernate, JPA och JDO. Transaktionsstödet kan användas på två sätt, deklarativt eller programmatiskt. Det deklarativa sättet är det absolut vanligaste och innebär att metadata kring transaktionslogik inte ligger inbäddad i den faktiska javakoden utan enbart finns deklarerad ”utanför” javakoden via metadata. Metadata kan antingen bestå av externa XML-filer eller annotationer och påverkar alltså inte javakoden, den är så att säga non-intrusive.

Läs mer >>

Grails är ett webbramverk som är designat för hög produktivitet. Det gör precis som Ruby On Rails och satsar på konventioner framför konfiguration. Detta förenklar och snabbar upp utveckling betydligt. Under motorhuven så använder sig Grails av bland annat Spring, Hibernate, SiteMesh, Ant, Log4j. Grails är baserat på Groovy, som är ett objektorienterat dynamiskt skriptspråk som är baserat på Java platformen.

Läs mer >>

RAP (Rich Ajax Platform) är ett nytt AJAX-ramverk som nyligen släppts av Eclipse Foundation.

I grunden ligger en portering av SWT (Standard Widget Library). RAP-applikationer utvecklas liksom andra Eclipse-plugins baserat på OSGi men kan även liknas vid GWT (Google Web Toolkit). Den stora skillnaden mellan RAP och GWT är att RAP-logiken exekveras på servern och RAP renderar GUI:t under körning via JavaScript, GWT å andra sidan skapar JavaScript vid kompilering och allt exekveras på klientsidan.

Kolla även in nedanstående länkar för mer information:
http://www.eclipse.org/rap/demos.php
http://www.thescreencast.com/2007/10/first-look-at-eclipse-rich-ajax.html

Under många år har debatten pågått om hur Java Modules ska realiseras. På ena sidan står OSGi-anhängarna (JSR 291) med IBM i spetsen och på andra sidan står Sun (JSR 277 och JSR 294). Nu har debatten tagit ny fart i och med att Java EE 6 är på gång (JSR 316).

Kolla in nedanstående länkar för lite information om vad statusen är på dessa JSR:er och hur 277:an egentligen hänger ihop med 291:an.

Sida 1 av 212