Silver för Sveriges svenskaste jobb
Postad av Christer (Isotop) i Nyheter, Syrup STHLM den 20 november, 2009
Kampanjen “Sveriges svenskaste jobb” för Svenska Turistföreningen vann ett silver i kategorin “Årets digitala kampanj” i tävlingen Spinn 2009.
De tekniska lösningarna i kampanjen producerades av Isotop tillsammans med byrån Syrup STHLM som stod för idé, koncept, design och genomförande.
Spinn anordnas av branschföreningen PRECIS och hölls första gången år 2004 vilket gör årets tävling och gala till den fjärde.
Vill du jobba på Isotop?
Postad av Stefan (Isotop) i Jobb, Nyheter den 20 november, 2009
Nu är det dags att förstärka vårt utvecklingsteam igen! Vi tror att du har några års erfarenhet inom webbutveckling och att du har en akademisk eller yrkesinriktad utbildning som grund. Din tekniska profil är bred och omfattar förutom .NET även gärna andra plattformar som PHP och Java.
Kunskaper om avancerad gränssnittsutveckling (t ex jQuery och AJAX) och moderna webbstandarder (CSS 3, XHTML, XML, microformats mm) är också meriterande då vi ofta levererar lösningar med höga krav på både funktion och tillgänglighet. Har du erfarenhet av EPiServer CMS så är det också ett plus.
Isotop är en framgångsrik webbteknikbyrå som arbetar med välkända varumärken och kunder som 3, NCC, Handelsbanken, Svenska Turistföreningen och TV4. Vi utvecklar webbapplikationer och webbplatser - ofta i samarbete med ledande reklam- och webbyråer. I dessa projekt bidrar vi med teknisk spetskompetens.
På Isotop är vi idag ca 20 anställda som arbetar i trevliga lokaler på Brunnsgatan 6 nära Stureplan i centrala Stockholm. Bolaget har funnits sedan 2001 och har vuxit i takt med att kundernas efterfrågan har ökat. Vi är rädda om vår personal och har en väldigt låg personalomsättning. Just nu satsar vi mycket på utbildning och utveckling både i det dagliga arbetet, men också genom utbildningar, kurser och konferenser.
Nu hoppas vi såklart att du är den vi letar efter! Skicka en ansökan och en meritförteckning till stefan.jansson@isotop.se eller slå en signal på 0733-55 00 27 så berättar Stefan mer om företaget.
Isotop söker erfaren webbutvecklare
Postad av Stefan (Isotop) i Jobb, Nyheter den 20 november, 2009
Isotop är en framgångsrik webbteknikbyrå som arbetar med välkända varumärken och kunder som 3, NCC, Handelsbanken, Svenska Turistföreningen och TV4. Vi utvecklar webbapplikationer och webbplatser - ofta i samarbete med ledande reklam- och webbyråer. I dessa projekt bidrar vi med teknisk spetskompetens.
Vi har flera spännande uppdrag som erbjuder utmaningar för dig som hos oss vill växa in i rollen som tekniskt ansvarig inom webbutveckling. På Isotop kommer du att arbeta i ett team som helt och hållet fokuserar på teknik. De lösningar vi levererar utvecklar vi tillsammans med våra kunder och i samarbete med andra specialister, till exempel design-, reklam- och webbyråer.
I rollen som tekniskt ansvarig arbetar du med systemdesign, modellering och utveckling, och då i första hand för Microsoft .NET och EPiServer. Vi tror att du är en person som drivs av att lösa problem och som inte är rädd för söka en väg som är annorlunda och utmanade. I ditt arbete kommer du att ha mycket kundkontakt. Du bör vara en hängiven tekniker men också en duktig pedagog då komplicerade lösningar ibland kräver enkla förklaringar för att förstås av uppdragsgivare och partners.
Eftersom du är en nyckelperson i arbetsgruppen bör vara lyhörd och duktig på att fånga in olika perspektiv och synpunkter. För även om du har huvudansvaret för att den lösning vi bygger fungerar så är det som lagspelare du presterar.
På Isotop är vi idag ca 20 anställda som arbetar i trevliga lokaler på Brunnsgatan 6 nära Stureplan i centrala Stockholm. Bolaget har funnits sedan 2001 och har vuxit i takt med att kundernas efterfrågan har ökat. Vi är rädda om vår personal och har en väldigt låg personalomsättning. Idag satsar vi mycket på utbildning och utveckling både i det dagliga arbetet, men också genom utbildningar, kurser och konferenser.
Nu hoppas vi att du är den vi letar efter! Skicka en ansökan och en meritförteckning till stefan.jansson@isotop.se eller slå en signal på 0733-55 00 27 så berättar Stefan mer om företaget.
Unit testing med Roy Osherove
Postad av Nils W (Isotop) i Blogg, Nils den 13 november, 2009
Hade nöjet att under TechEd Europe delta i en session med Roy Osherove, som till vardags arbetar som chefsarkitekt hos Typemock och även skrivit boken ”The art of unit testing”. Det initiala sessionsnamnet var ”Unit Testing - Best practices”, vilket han efter en kommentar i sista minuten reviderat till ”Unit testing – Good practices”.
Vad är då ett unit test och vad definierar ett bra sådant?
Ett unit test är en metod som testar vissa antaganden mot en annan klass eller metod. Ett exempel på ett enkelt unit test är följande.
[Test]
public GetCityById_NegativeNumber_NameIsNull()
{
City c = GetCityById(-1);
Assert.AreEqual(c.Name, null);
}
Vi testar alltså om vår GetCityById metod returnerar null då vi skickar in ett negativt nummer som parameter. För att kunna skriva ett bra unit test måste vi dock först definiera vad som är ett integrationstest och vad som är ett unit test. Osheroves definition av ett unit test är:
- Snabbt
- I minnet
- Inga externa beroenden (mot filsystem, databaser etc.)
- Samma process
- Automatiserat
- Repeterbart
- Konsekvent
När vi nu vet vad ett unit test är, kan vi med fördel dela upp våra unit och integrationstester i olika namespaces eller projekt. Genom att göra en uppdelning av våra tester har vi sedan en klar bild över vilka av våra tester som har externa beroenden, och vilka som vi kan köra som unittests.
En viktig sak Roy nämner är vikten av att lita på sina tester. Litar man inte på dem och använder debuggern för att dubbelkolla förlorar testet sitt syfte. En av anledningarna till att man inte litar på sina tester kan vara att man inte delat upp sina tester och då har ett antal integrationstester som behöver viss konfiguration innan de passerar, men vanligast är att man helt enkelt känner att testerna inte riktigt går att lita på.
Så, hur kan jag börja lita på mina tester?
För att kunna lita på mina tester, måste jag lita på min egen förmåga att skriva bra test. För att göra detta gäller det att inte tumma på vare sig struktur eller läsbarhet. Roy har ett par bra tips när det gäller namngivning.
Ha en konsekvent namngivning på dina testmetoder. Gärna enligt [metodundertest]_[scenario]_[resultat], vilket bli extra tydligt om vi jämför metoderna AddNumber_LessThanZero_ThrowException() och AddNumber().
Man måste också se till att döpa sina variabler korrekt och att undvika Magic numbers. Om vi jämför en assert av typen Assert.AreEqual(-77,statuscode) med att använda en konstant/variabel MISSING_COUNTRY=-77, märker vi hur mycket läsbarheten ökar då vi istället får Assert.AreEqual(MISSING_COUNTRY,statuscode).
Med vackra ord, eller i det här fallet KONSTANTER och metodnamn, kommer man inte långt om testet i sig är inte känns stabilt. För att undvika problem i dina tester finns ett (stort) antal saker att hålla koll på, här är några av dem.
Endast ett test per metod, har du flera tester (asserts) i en metod bör du bryta ut dem till egna tester. Detta gäller dock inte om du skall testa flera properties i ett och samma objekt.
Undvik logik i dina tester, har du ett antal if-satser som styr logik i ditt test kan du troligtvis refaktorera dem till egna tester.
Repeterbarhet, undvik saker som gör att varje test blir unikt. Använd ett statiskt datum istället för DateTime.Now och håll dig långt borta från allt vad slumptal heter.
Summering
Detta var bara en liten del av det som togs upp under sessionen, vilken allt som allt var mycket lärorik, även om det traditionella gitarrspelandet uteblev (den var trasig). Kan även passa på att rekommendera boken ”The art of unit testing” där han går igenom ämnet unit testing mer ingående.
TechEd Europe 2009 i Berlin
Postad av Rikard (Isotop) i Blogg, Rikard den 13 november, 2009
Isotop har under veckan haft två representanter nere i Berlin på TechEd-mässan som hålls varje år i Europa. Totalt hade ca 7200 teknikintresserade personer, varav 325 svenskar hittat hit för att förkovra sig i Microsofts olika teknologier. Utöver teknikfokuset har det också firats en del då mässan sammanträffade med 20-årsjubileumet av berlinmurens fall.
Veckan har bjudit på flera höjdpunkter men även några besvikelser då fokus legat på IT-infrastruktur och inte programmering och webbutveckling, vilket är Isotops huvudspår. Man hör ofta folk på TechEd säga att ”alla snackar om molnet”, men det är fel… sanningen är att alla snackar om Sharepoint 2010 och Exchange.
Några reflektioner från veckan på TechEd där temat var ”The new efficiency”:
David Chappelle hade en dragning om Windows Azure-platformen ur ett IT-strategiskt perspektiv där han försökte besvara frågorna – När, hur och varför man ska använda molnet? Microsoft planerar att släppa Azure i nästa vecka (19:e November) och funderingarna kring detta är många. Ett vanligt orosmoln från intressenter är säkerheten, vågar vi skicka upp vår känsliga data in i molnet? Microsoft har insett att plattformens pålitlighet är avgörande för att vinna kundernas förtroende. Det har i sin tur inneburit att de infört vissa begränsningar som förenklar systemet men ökar pålitligheten, t.ex. kommer databaser till en början ha en maxstorlek på 10 GB och lastbalanseringen sker via manuell konfigurering. Läs gärna mer om Windows Azure och molntekniken i Staffan Eketorps inlägg Moln i praktiken, del 1 och Moln i praktiken, del 2.
För den intresserade utvecklaren har Microsoft utlyst en tävling där man ska bygga molntjänster. Läs mer på http://wadc.cloudapp.net/
För oss vanliga dödliga finns det fortfarande ett alternativ till molnbaserad hosting. Windows Server 2008 R2 och IIS 7.5 kommer med några intressanta nya features, bl.a. Centralized Web Management som innebär att man kan styra en hostad IIS från en lokal klient. Microsoft har också tagit fram ett verktyg (IIS Web Deployment Tool) för att underlätta installationer direkt från IIS genom konfigurerade export/import-funktioner. Det mest intressanta måste ändå vara Web Platform som innebär färdiga paketinstallationer av bloggverktyg och CMS som Wordpress, Umbraco och DotNetNuke. Site Analysis Report är också en annan feature som gör att vi kan hämta ut rapporter om t.ex. sökbarheten/tillgänglighet på webbplatsen. Listan kan göras lång och det blir helt klart spännande att se hur EPiServer anammar denna miljö i kommande versioner av EPiServer CMS.
Visual Studio 2010 och .NET 4.0 har nyligen släppts som beta 2. En av de mer intressanta nyheterna i .NET 4.0 för utvecklare är Parallel Extensions som förenklar parallellisering av många vanliga programoperationer, t.ex. loopar och (P)LINQ.
IronPython och IronRuby är något som omnämns titt som tätt här på TechEd. Båda språken har fullt stöd i 4:ans DLR (Dynamic Language Runtime) och innebär helt klart intressanta möjligheter för den som inte känner sig hemma med C# eller övriga .NET-språk. Dynamiska språk öppnar en ny värld för utvecklare från andra miljöer, inlärningströskeln för t.ex. en Ruby-utvecklare blir minimal samtidigt som man exponeras för styrkorna i .NET Framework. IronPython och IronRuby kan säkert vara intressant i vissa specifika fall men i grund och botten så innebär det ännu inga prestandavinster jämfört med andra implementationer av språk , snarare så leder det generellt till sämre prestanda, vilket Harry Pierson påpekar under sessionen ”Pumping Iron”.
Veckan har bjudit på många inspirerande talare, sessioner och ämnen. Nu behöver dessa tankar landa innan vi lanserar vår första IronPython-applikation på molnet.
Läs gärna inlägget ”Tips för att snabba upp din webbplats” och ”Unit testing med Roy Osherove” som sammanfattar två enskilda föreläsningar från Microsoft TechEd 2009 i Berlin.
Tips för att snabba upp din webbplats
Postad av Rikard (Isotop) i Blogg, Rikard den 12 november, 2009
Denna post innehåller en sammanfattning av sessionen ”Tips and Tricks for Building High Performance Web Applications and Sites” från Microsoft Tech Ed 2009 i Berlin.
Giorgio Sardo höll i sessionen som handlade om hur vi kan göra våra webb-2.0-applikationer och webbplatser snabbare. Fokuset låg helt på klientsidan och handlade till stor del om optimering av Javascript och DOM-operationer som står för 33% av CPU-förbrukningen för den genomsnittliga webbplatsen (övrig CPU går till rendering av innehållet).
Sessionen och talaren Giorgio Sardo, som är ”Technical Evangelist” på Microsoft Corporation, kanske var lite smått färgad av just Microsoft men framhöll ändå några intressanta synpunkter och fallgropar man bör tänka på när man utvecklar gränssnitt – oavsett plattform (oroa er inte, jag hade mina GOOGLES på mig).
Några vanliga fallgropar på klientsidan
- CSS - Långa selektorer drar prestanda. Håll dem korta och koncisa.
- CSS - Undvik CSS Expressions.
- JS - Undvik globala variabler om det går.
- JS - Undvik arv med prototyping. JS-motorn måste först leta igenom objektinstansens alla default-properties innan den kan söka vidare efter prototype-funktioner. Det drar prestanda.
- JS - Cacha get/set anropen till DOM genom temporär lagring i lokala variabler.
- JS - Precis som ovan så bör man även cacha återkommande funktionsanrop i lokala variabler.
- JS - Vid användning av setTimeout() bör funktionsanropet göras direkt och inte via en sträng. Strängar som skickas till setTimeout måste exekveras med eval() vilket leder till prestandaförluster.
Exempel - vanligt förekommande:
setTimeout(”testFunc()”,100);
function testFunc() {alert(’Hello world!’)}Exempel - rekommenderad användning:
setTimeout(function(){testFunc()},100);
function testFunc() {alert(’Hello world!’)}
- JS - for-loopar blir snabbare om de utgår ifrån en lokal variabel med length-värdet istället för att gå direkt mot object.length.
- JS - Iterationer över DOM-element bör göras med while-loopar där nextSibling() styr iterationen. På detta sätt undviker man onödiga uppslagningar mot DOM-objekten.
- JS - IE 8 kommer med en native selector som (enligt Microsoft) går snabbare än jQuerys selector.
- JS - Konkatenering av strängar bör göras genom att pusha strängar till arrayer som i slutändan sammanfogas med join() istället för att addera (var1 + var2) strängar med varandra.
Några intressanta verktyg som togs upp under sessionen
Doloto
Doloto är ett verktyg för att optimera Javascript-filer, inte genom minifiering utan genom klustring av funktioner. Verktyget analyserar vilka funktioner som anropas i runtime och utifrån det resultatet så optimeras koden dels genom uteslutning av överflödig kod och dels genom lazy loading. Det huvudsakliga målet är att reducera väntetiden för en webbsida att laddas in.
Läs mer på http://msdn.microsoft.com/en-us/devlabs/ee423534.aspx
Expressions Web 3 + SuperPreview
Verktyg för att felsöka grafiska skillnader mellan olika versioner av IE(IE6 + IE7 eller IE8) och Firefox. Via en och samma vy kan man göra snabba visuella analyser över vad som skiljer sig åt mellan de olika webbläsarna.
Läs mer på http://blogs.msdn.com/xweb/
Advanced sound programming in AS2
Is it possible to synchronize sounds with good precision in AS2 to create a beat box? You want those bass drum sounds pounding on 1, 3 while digging a nice groovy tight hi-hat. And sync problems: no thanks! Lots of people have experienced problems, but read on to get some code and 7 strategies to get there. Or…browse to the end and download some code.
Some time ago, we faced the problem of building a little audio/video sequencer in Flash. With this sequencer the user would produce his/her own music video that was published on YouTube. As for video, there wasn’t much problems, but synchronizing audio turned out to be a real beast. Following the debate on Andre Michelle’s blog and http://www.make-some-noise.info/2008/04/01/response-to-a-bunch-of-questions-from-adobe/ Adobe hasn’t really been the Flash sound community’s dear friend recently. In short, they introduced severe bugs in Flash player 9.r115, but they changed the whole API for version Flash Player 10. With version 10 you can do really cool stuff writing directly to sound mixer buffers. In particular: see Hobnox’s Audiotool which is probably the coolest Flash application I’ve ever seen (ReBirth anyone? :-)).
Anyhow, unfortunately our project couldn’t go for Flash Player 10 as the market penetration wasn’t large enough. Even AS 3 was not an option due to platform restrictions. So, back to thinking in terms of the old API:s and playing around. The idea was for the user to click in a grid and play different samples, just like a beat box or drum machine. Furthermore, each sample had a video so, in effect, the user made a little video beat box loop. Ok, cool…but could we accomplish this?
After trying just naive Sound.play calls together with matching timer values from getTimer() and noticing quite large rythmic glitches I was disappointed. Clearly, we needed better timing information. But reading the article Advanced Flash MX Sound Timing made it clear. There is one exact timing for sounds in Flash, namely the Sound.position property. In order to use this for common timing information, we needed to play a really long sound, and then we could check where we were in this reference sound. As we’d see, we’d get position increases in chunks of 46.4 ms. It turns out that this corresponds to the buffer size used by Flash (2048 samples 44.1 KHz) and sometimes (NOTE: not always) when the soundcard calls back to get more data to play, Flash updates Sound objects’ position values. So I started a really long, totally quiet, sound to play in parallel for common timing, but it quickly struck me that a smart approach would be just to loop something like a 1 second sound. I’d found my first conclusion:
1. Use a silent reference sound and loop this sound. For each loop we can increase a counter and thus we can always reach the overall position. A reasonable length is probably 1 second. Make sure it’s mono by the way.
Ok great! Things were clearly better. Only - quite many sounds still came slightly wrong and misaligned musically. After thorough investigation, it turned out that when you say Sound.play to Flash, this doesn’t really happen immediately. Not even on the next sound card callback. But rather on the next sound card callback which Flash happens to like. (My guess: where some low prioritized task queue copy function for some other thread has completed).
2. So the solution is to use some silence in the beginning of the audio, and schedule the sound to play “in the future”. We thus introduce a little latency, but we really have the ability to sync sounds given a little latency of say 200 ms. If we schedule audio every 200 ms, we need at least a 200 ms silent part before each sound, and then we can just check the position of the reference sound and use Sound.start(OFFSET) to start a sound with a little offset that has been calculated from the position. This is actually much better explained at Advanced Flash MX Sound Timing. Great! But it turned out that there were still glitches.
3. Enter 1 short 1-sample silent mono sound that we don’t loop but re-trig all the time. Yes, just as it had been suggested by Advanced Flash MX Sound Timing and others. It turns out that callbacks at onSoundComplete are really good for starting new sounds, even though they don’t always come when the sound has actually finished (as pointed out by very disappointed people at http://www.make-some-noise.info). Anyhow…still great for our purposes! To be clear: the idea is basically to just start this one-sample sound and use its onSoundComplete handler. In that handler, we just trigger the little sound again. And so on. This way we get a callback on “good” times, instead of using setInterval or onEnterFrame. Super! So we now have a longer sync sound that we loop for position, and a shorter sync sound for good callback times. But…happiness didn’t last for long. Even though the situation had clearly improved there were still glitches every now and then. If you weren’t picky or perhaps playing some rather soft/smooth sounds, perhaps you didn’t care. But we had this smackin’ snare and hand clap we wanted to make a groove of and glitches aren’t grooves’ best friends.
4. It turned out some old fashioned pickyness, good system design and loads of asserts were bringing in some predictability. Starting a Sound in Flash isn’t just a few-instructions synchronous little thingie. It actually takes a couple of milliseconds. And by starting a lot of sounds, the master position could have changed, and then those recently started sounds were out of sync. Even on direct callbacks from the onSoundComplete handler previously mentioned the master clock sometime changed directly. Ok, so by just avoiding scheduling sounds at those positions seemed to do the trick quite well. But we now needed to increase the quite part in the sounds, since REALLY GOOD callback times occurred more seldom. Ok, still cool, but….still glitches. Shit! But some more coffee revealed a more serious approach to solving this.
5. Enter error detection. Yep, we could always check the positions of Sound objects that we schedule to see if they match what we expect them to have compared to the master position. This meant that we had to rewrite the scheduling mechanism. Instead of just using play, we now added sounds to a queue and then removed them when they had been deemed “OK” by some error detection handler. But…now it turned out the sync was really good. But…there were drop-outs. Yep, some sound could never be synced back, but an even more common problem turned out to be that it was really hard to read a sound’s position. Say you used the same kick drum sample on each beat, but when you were to read the position of that sound object, it might return the old sound object’s position and vice versa. This really exposed a nasty detail of the Sound API: namely that the Sound object plays two roles: to wrap some audio file and to provide information about currently playing material. A more clean solution more in line with how things work would probably be for the play function to return a PlayingSound (or similar) object which had the position. Anyhow, as that wasn’t available, we decided to build…
6. …a SoundPool class. The idea is to load a bunch, say 30, similar Sound objects in a pool. Whenever a new playing sound is needed, we could ask the pool for a “fresh sound” and the pool would just circle round the sounds and return them in circular order. How many sounds you need depends on how many sounds you play simultaneously, and also how long your silent intro is. We decided that ~30 was probably a quite good number. Notice that the browser cache would normally take care of not issuing more requests than necessary, but it’s probably wise to make the server return an Expiration Data in the HTTP header or similar for the mp3 files in question.
Now we had quite some solutions to deal with this. There was just the problem that when you filled the sequencer grid with beats (I know, not the grooviest of beats, kind of repetitive) sounds vanished and there was nothing heard. Aarrghh…going crazy again! When investigating this it turned out to be because of the sound channel limitation in Flash (currently 32 channels). So what happens is actually that if you have 32 channels playing and play another sound, one of the first sounds just stop. Unlucky for us all sounds start with silence, so we were listening to 32 channels of groovy silence. Not cool.
7. Enter cancel mechanisms on scheduling when too many sounds are playing. Yes - we adapted our scheduling mechanism so that when a sound was OK in sync we moved it to a playing collection and continuously removed sounds from that queue when they finished. Thus we could keep track of how many sounds were playing and cancel any scheduling attempts. We just simply had to wait for some sounds to complete. Sure, this meant that we had fewer times to sync audio, but it still worked quite well.
Ok, but there were still occasional drop-outs
Yep, we decided to live with it. It really happened quite seldom, and we set a limit on 100 ms drift to regard a sound as playable even though not in sync.
Next thing: sync with video. We needed to provide some video along with the sounds as well. We just used an onEnterFrame callback and calculated the approximate position. When we had the latest callback we saved the position using a getTimer() call and then we could just diff a getTimer() to the last call to calculate a continuous position which we could then use for video. Our video actually started 85 ms before the audio se we showed the corresponding video on the first frame ~85 ms before the sounds was going to be heard.
So - how can you use this code? Just check out the Main.run function which demonstrates an example. Furthermore, check each classes header to see some documentation in comments.
If you really want, I could probably include a demo too =) Just contact me or leave a comment below.
Good luck!
