Thursday, January 19, 2012

Intressant från Fog Creek; varför har säljare provision?

Among our many cherished verities and assumed assumptions is the widespread belief—nearly universal practice actually—that salespeople are to be paid commissions. It’s the way things are done. Stop signs are red. Salespeople get commissions.

But why? 

Intressant om provision från Fog Creek (skaparna av StackExchange), som själva lagt av med det:

Why do we pay sales commissions? [Fog Creek Blog]

As John, one of our salespeople said, “It’s made the team better. It’s removed the ‘me, me, me’ mentality. Now I want to share information with everyone on the team, and everyone is willing to pitch in because it doesn’t hurt me to help my colleagues.”

Wednesday, January 18, 2012

Google, Wikipedia, Reddit, Craigslist, Flickr stänger i protest mot SOPA/PIPA



Såhär ser Google ut idag i USA.

Idag stänger flera stora sajter för att protestera mot lagförslagen PIPA och SOPA (i den amerikanska senaten respektive representanthuset): http://americancensorship.org/infographic.html

"YouTube would just go dark immediately," Google public policy director Bob Boorstin said at a conference last month. "It couldn't function."

Bland de som stänger:
Wikipedia (http://en.wikipedia.org/wiki/Main_Page)
Reddit (http://www.reddit.com/)
Craigslist (http://philadelphia.craigslist.org/)
Wordpress (http://wordpress.com/)
Free Software Foundation (http://www.gnu.org/)
Mozilla (http://www.mozilla.org/)
Flickr (http://www.flickr.com/)

Monday, January 16, 2012

Reblog #1: Facebook Social Plugins, The Aura Project, Shim, 3D i WebKit, JQ.Mobi

Facebook uppdaterar sina social plugins, inget superintressant där: http://klinger.io/post/15672435659/the-unannounced-updates-to-facebooks-social-plugins

The Aura Project siktar in sig på PHP 5.4 istället för 5.3; utmanare till Symfony2 möjligen: http://paul-m-jones.com/archives/2219

Boston Globe släpper testverktyget Shim på Github, Javascript/Wifi-hack som gör så att flera enheter delar cookies och surfar till samma URL:er på samma gång. Givet om man ska testa responsive design: https://github.com/marstall/shim/

Making Love To WebKit, 3D i Safari med endast CSS. Firefox och Chrome verkar på g. Synd bara att vi måste vänta ut IE6, IE7, IE8 och IE9 innan det kan bli aktuellt att använda i större sammanhang: http://acko.net/blog/making-love-to-webkit/ (kolla sidan i Safari för bästa effekt, hint: scrolla upp)

JQ.Mobi; ett vettigt alternativ till jQuery Mobile? Snart kanske: http://www.readwriteweb.com/mobile/2012/01/jqmobi-is-a-mobile-optimized-h.php

Sunday, January 15, 2012

Google: Don't be evil?

Mocality secretly recorded Google employees offering to build a website for the businesses and, in one case, falsely claiming that Mocality would charge to list its business. (The Guardian)

Mocalitys blogginlägg: http://blog.mocality.co.ke/2012/01/13/google-what-were-you-thinking/

Google ber om ursäkt: http://www.guardian.co.uk/technology/2012/jan/13/google-kenyan-rival-mocality-database

Sammanfattning, från Guardian-artikeln:
According to Magdalinski, suspicions were raised after Mocality started receiving calls from businesses on its directory asking how they shoud go about setting up a website – which Mocality has never offered.

Mocality then set up what it described as a "sting" operation, changing some of the telephone numbers on its business directory to the contact details of its own call centre.

"When we listened to the calls, we were beyond astonished," said Magdalinski.

Mocality secretly recorded Google employees offering to build a website for the businesses and, in one case, falsely claiming that Mocality would charge to list its business.

"Since October, Google appears to have been systematically accessing Mocality's database and attempting to sell their competing product to our business owners," Magdalinski wrote in the blogpost. "They have been telling untruths about their relationship with us, and about our business practices, in order to do so.

"I did not expect to find a human-powered, systematic, months-long, fraudulent (falsely claiming to be collaborating with us, and worse) attempt to undermine our business, being perpetrated from call centres on two continents."

Friday, January 13, 2012

Symfony 2: Inte bara ett framework

Blir mer och mer imponerad av Symfony 2, speciellt efter Fabien Potenciers (hittills) sex delar långa guide om hur man använder Symfony 2:s komponenter till att bygga sitt egna framework.

Välj och vraka mellan byggstenarna helt enkelt; och samtidigt en inblick i tankarna bakom uppbyggnaden av Symfony 2 Standard.

Här är del 1: Create your own framework... on top of the Symfony2 Components

Wednesday, January 11, 2012

iDoneThis: Få saker gjort genom att se vad andra får gjort

I mängden av nyårslöftesrelaterade startups hittade jag iDoneThis.

Du signar up med din e-post och beskriver det du vill få gjort, och om du vill få det gjort varje dag eller varje vecka.

Efter ett par dagar har du blivit tilldelad en slumpmässigt utvald grupp, kring 20 personer. Du får då ett mail som beskriver vad varje deltagare i just din grupp har gjort under gårdagen, samt en uppmaning att svara på mailet och beskriva vad du har gjort idag.
We probably didn’t need scientists to actually come up with a figure (80% failure rate!) to know that New Year’s resolutions don’t stick.

Instead, build a habit! You can start with baby steps, like drinking water instead of soda, attaining small successes and rewards that will build up until voila, habit!

The ever-helpful Zen Habits has great tips on building habits: make it enjoyable, commit to one habit at a time, and harness the power of a social network.

Tell us your New Year’s Habit and we’ll match you up in teams of people building similar habits. We'll keep you on track with a nightly email reminder. Just reply with what you did. The next morning, you’ll get an email with your team's progress, and you’ll be on your way to long term-change slowly but surely.

Utdrag ur dagens iDoneThis-mail för min grupp:
  • Wrote for 20 minutes on my pilot.
  • Reworked horror novel opening.
  • still working on the same lyric. feels a little like waiting at a bus stop for the express to come by. no timetable in sight, but i'm here until it arrives.
  • Finished a draft! We'll see how it reads in the morning.
  • No writing, but caught up on some overdue emails.

Tuesday, January 10, 2012

Sushi till middag

Sushi till middag

Gött.

Monday, January 9, 2012

jQuery Mobile: Diverse problem

jQM tar för mycket kraft att ladda om vid varje sidladdning; speciellt i mobila enheter. Det självklara valet blir då att bara ladda jQuery och jQM en gång; och sedan ladda påföljande sidor med hjälp av AJAX (detta är dessutom ganska djupt inbyggt i jQM:s navigeringslogik).

Då stöter vi på ett antal problem.

404: File not found
Om man stöter på en sida som returnerar en felkod som jQuery:s AJAX-anrop tolkar som ett "error"; exempelvis 404, så visas inte svarssidan alls. Istället får man ett felmeddelande från jQM:s navigeringssystem, och lämnas kvar på sidan man befann sig på tidigare. Detta är dessutom klurigt att ändra utan att göra ganska stora förändringar i jQM-koden, som då blir ett helvete att underhålla när det ska uppgraderas.

Enklaste "lösningen" är att helt enkelt inte skicka "rätt" HTTP-felkoder från backend, utan att alltid skicka 200 OK när innehållet faktiskt ska visas. Detta är inte något större problem om det inte handlar om en sida som Google ska indexera; där felkoderna faktiskt fyller en funktion.

Sidspecifik JS/CSS
I den lösning jag jobbar i nu så byggs ett block med JS och ett block med CSS för varje kombination av templates. Så vid första sidladdningen laddas alltid bara den JS och den CSS som behövs för den sidan; inte mer. När man då byter sida med hjälp av AJAX så kommer jQM inte att plocka ut CSS/JS från HEAD-delen av svaret, utan bara plocka ut själva DIV:en med sidans innehåll.

Detta bör gå att lösa genom att lyssna på lämpligt jQM-event; parsa HEAD-delen av svaret själv, och kopiera in nyupptäckt CSS/JS i sidans riktiga HEAD-del innan den nya sidan visas ut.

Annonser
Vår gamle vän document.write dyker som vanligt upp i AJAX-sammanhang. Annonskoder håller i regel stenåldersnivå; det krävs document.write i minst två led för att fungera, och dessutom kräver eventuella tredjeparts-taggar ännu ett eller två led för att få ut något.

På desktop-sidan har vi löst detta med en modifierad variant av LazyWrite som fungerar relativt bra i nyare webbläsare. I övriga låter vi helt enkelt document.write göra sitt; vilket ju är ett alternativ när man inte laddar om hela sidan med AJAX.

Återstår att se om LazyWrite är lösningen även på mobilsidan. Preliminära tester visar att det åtminstone inte fungerar rakt av. Gissningsvis har det att göra med hur jQM hanterar SCRIPT-blocken i de AJAX-hämtade sidorna, och förhoppningsvis går det att göra något åt genom att lyssna på något event.


Återkommer förhoppningsvis med lösningar, och en separat post om den där CSS/JS-implementationen.

Saturday, January 7, 2012

Friday, January 6, 2012

Thursday, January 5, 2012

Nyårslöftesrelaterad idé

Starta en sida där man registrerar sig och ger ut antingen kreditkortsnummer, eller sätter in en summa pengar, mot att man uppfyller sitt löfte (exempelvis träna 2 ggr/vecka).

Uppfyller man det inte (behöver inte direkt kontrolleras, utan kan vara samvetsstyrt), så dras det en mindre summa från ens konto. Alternativt om man satt in pengar; uppfyller man löftet för den veckan/månaden, så får man en del av pengarna tillbaka.

Om man inte vill blanda in pengar: Koppla till Facebook, avge ett löfte; om du inte följer löftet så postar den till alla dina vänner om hur dålig du är. Ifall du sagt att du följt löftet för den veckan, så postar den tid/datum då du påstod att du gymmade, och ber dina Facebook-vänner kommentera ifall du faktiskt gjorde det eller inte.

Wednesday, January 4, 2012

Fantasy Premier League - Gameweek 20

För tätt mellan gameweeks på sistone, glömt av transfers två gånger senaste fyra omgångarna.

Denna vecka spelar Spurs två matcher, men jag glömde såklart att sätta Bale som kapten.

Och givetvis spelar inte Larsson, och istället tar Sessegnon 10 poäng; som jag köpt först till nästa vecka.

Hittills står det 29 - 48 i veckans cup-match; med Ba, Rooney, Nani och Bales andramatch kvar att spela. Min motståndare har dessutom både Van der Vaart och Bale, med Van der Vaart som lagkapten. Allt hänger alltså på att MUN-NEW blir väldigt målrik. Och att VdV bryter båda benen under uppvärmningen.

Nästa vecka har jag nog bättre förutsättningar; Sessegnon inköpt (för andra gången), och lite fräschare bänk.

Monday, January 2, 2012

Varnish är min vän (och libvmod-header)

Efter många timmars testande och googlande har jag byggt en lösning som jag är hyfsat nöjd med.

Några saker jag lärt mig:
- Varnish har inte så bra stöd för ETags som jag trodde
- Varnish är sjukt snabbt
- Ingen gillar Set-Cookie-headern; och browsers gillar speciellt inte när man merge:ar flera Set-Cookie-headers till en (även om det ska vara lugnt enligt RFC:n)

Då till problemet; jag ville ha flera parallella versioner av en resurs, som utåt sett skulle ha samma URL. För att veta vilken av dessa som ska hämtas behöver man minst ett anrop till backend.

Utöver detta vill jag helst kunna få cookies från backend vid varje sidvisning; om det absolut inte går vill jag strippa Set-Cookie-rader helt från cachade svar. Detta skulle dock resultera i att en massa oanvända sessioner startas, men skulle nog gå att komma förbi på något sätt.

ETags galore?
Först försökte jag olika lösningar med ETags, Vary: ETag, 304-svar från backend, osv. Lyckades dock inte få det att funka, då Varnish inte skickar If-None-Match om inte klienten skickat det, och då blir det ingen gemensam cache; och alltså ganska värdelöst.

302 Found
Så, vi skippar ETags helt; vi behöver en unik URL för varje version av resursen. Kan vi då dölja denna URL för besökaren? Vi bakar helt enkelt in ETag:en i URL:en istället.

- Varnish frågar backend efter resursen med URL "/forum"
- Backend svarar med en 302-redirect till "/forum?etag=foo"

Här kommer det vackra, i vcl_fetch;
if(beresp.status == 302) {
        set req.url = beresp.http.location;
        return (restart);
}
Redirecten hanteras nu alltså internt av Varnish, klienten har ännu inte fått något tillbaka.

- Backend svarar på "/forum?etag=foo" med en helt vanlig sida, med lämpliga cache-headers
- Varnish cachar sidan med ETag:en i URL:en, och skickar den till klienten
- Nästa gång någon hämtar samma resurs och den fortfarande är kvar i cachen med samma ETag så kommer den bara träffa backend en gång (då den får 302-svaret)

Cookies då?
Vi gör ju faktiskt redan en helt vanlig request mot backend som har klientens cookies med sig. Vi sparar helt enkelt Set-Cookie-raderna vi får tillbaka, i den nya requestens header X-COOKIES i vcl_fetch:
if(beresp.status == 302) {
        set req.url = beresp.http.location;
        header.copy(beresp.http.Set-Cookie, req.http.X-COOKIES);
        return (restart);
}
Sedan i vcl_deliver så plockar vi ut dessa och lägger i Set-Cookie på vårt svar:
unset resp.http.Set-Cookie;
header.copy(req.http.X-COOKIES, resp.http.Set-Cookie);
Detta vore inte möjligt utan libvmod-header, som tillhandahåller header.copy-funktionen. Om man hade använt Varnish inbyggda funktioner för att sätta Set-Cookie så hade man nämligen bara fått med den första Set-Cookie-raden om det varit flera.

Sunday, January 1, 2012

Varnish, Etags, och Cache Invalidation

Försöker hitta en optimal lösning för Varnish med hjälp av Etags. I princip tror jag att jag är ute efter att flera Etags kan vara giltiga samtidigt för en viss resurs.

Scenariot
- Tre olika klienter med tom cache gör varsin request, klient #2 är inloggad, #1 och #3 är inte inloggade.
- Varnish cache är tom innan första requesten görs
- Alla klienter hämtar samma sida, låt säga "/forum", inga edge side includes eller liknande.
- Back-end returnerar endast Etag och eventuellt 304-svar om klienten inte är inloggad. Annars returneras ett helt vanligt svar med privata cache-headers etc.

Om requesterna görs i ordningen 1-2-3
#1: Får fräsch sida, sparas i Varnish cache
#2: Får fräsch sida, Varnish cache rensas för objektet
#3: Får fräsch sida, sparas i Varnish cache

Om de görs i ordningen 1-3-2
#1: Får fräsch sida, sparas i Varnish cache
#3: Får cachad sida
#2: Får fräsch sida, Varnish cache rensas för objektet

Möjlig lösning
Konfigurera Varnish så att den inte gör något alls (specifikt; så den inte invaliderar cachen) om ingen Etag kommer från backend, utan bara skickar vidare requesten till klienten. Går säkert att konfa så, verkar ganska flexibelt.

Nästa problem: Flera valida Etags
Om vi har flera varianter av en sida, för olika typer av oinloggade besökare. Exempelvis vill vi cacha sidan olika för om webbläsaren stödjer lazyload av våra annonser eller inte. Då har vi plötsligt två eller fler konkurrerande Etags för samma resurs, som kommer invalidera varandra.

Detta borde dock Varnish kunna hantera; den skulle ju kunna skicka flera Etags med en "If-None-Match"-header till backend. Frågan är hur den ska veta vilken som ska invalideras när den får tillbaka en 200 istället för 304?