You are here: Home / Archive

Auteursarchief: admin

You are here: Home / Archive

Daily Developer Dose: DRYing up teh things with an extension method

An extension method for a DRYer way when changing key type of ASP.NET Identity Users and roles

Ah.. extension methods. What a great feature of C#! Making a simple developer feel a bit like a language designer, by adding custom OO style methods to C#’s base types or custom classes.

var now = DateTime.Now;
DateTime.Now.ToFunkyDutchDate()

But of course extension methods are also seen as design smells nowadays. An extension method is a static method which HAS to be in a static class and then prepending the methods’s first parameter with ‘this’:

static class MyExtensions {
public static void ToFunkyDutchDate(DateTime this theDate) {
return string.Format("{0:dd-MM-yyyy}", theDate);
}

Yikes did I say static? In the modern age of dependency injection and TDD it seems no use of the ‘static’ keyword is allowed anymore. Static fields are bad, because they make your code hard/impossible to test. And extension methods are suffering from ‘feature envy’ according to code masters like Jeff Atwood (though the guy self-admittedly he has no idea what he’s talking about ;).

But if you want to do everything right, things can sometimes turn out to be so much more work initially. Especially when working on an older code base. A lot of the times there is a customer waiting for a fix/feature he/she considers to be simple. But you find a little bug, chase it only to discover a whole heap more. Kind of like Homer Simpson in the intro of this video.

Ofcourse once you’ve cleaned everything up you feel better, and will have to trust it will pay back for itself later. But sometimes it’s better to just take on some technical debt, and leave some TODO’s in your code to refactor things later. So now and then they are just really convenient. Still I sometimes have a hard time with pragmatics like that. My current .NET project is actually brand spanking new, so I would like to keep it clean. Except that it’s based of of the .NET default application, and I have already found out that this standard code actually already contains some code already that is not particularly DRY. I’m using ASP.NET One Identity based on a Code First approach.

Today I changed the key for my (Identity) users from the default GUID to an int, because it just felt better. Microsoft provided a nic eblog post, a nice blog post describing how to di this. It basically comes down to subclassing a whole bunch of of the classes in their Identity NuGet package. However after doing the basic work I was still left with about 40 compile errors of strings that now had to be int:”
CompileErrors

The fix in all cases was to change

var userId = User.Identity.GetUserId();

into

var userId = User.Identity.GetUserId()

Since the `GetUserId()` was already an extension method itself, I decided to write my own. By swapping all uses with that I would only need to change it in this single place, if I later ever decided to change the type again (back to a GUID for instance) :).


using System.Security.Principal;
using Microsoft.AspNet.Identity;

namespace my.app.Extensions {
public static class IdentityExtensions {
// Central static method to make stuff DRY, so it’s a oneline change in the type of the Identity UserKey is changed again :).
public static int GetUserKey(this IIdentity identity) {
var result = identity.GetUserId();
return result;
}
}
}

Mijn oude SEO hoed weer eens op

Ik heb een aantal jaar Search Engine Optimization (SEO) gedaan toen ik nog in loondienst was. Of nou ja, erbij gedaan, naast reguliere ontwikkelwerkzaamheden. Vandaag had ik mijn oude SEO hoed weer eens op, en runde wat testjes op de Google Search. Dat verliep vlot, en toen had ik mijn resultaat. Maar net daarna kom ik een artikel tegen die mijn testresultaten direct tegen spreekt. Dat leek me de moeite waard om eens even een blog aan te wijden…

Voor SEO kun je met een paar gerichte ‘site:testsite.nl “tekst die je zoek”‘ zoekacties en het checken van de laatst door Google gecachete versie al best het een en ander uitvinden. Ook al had ik in dit geval niet direct toegang tot Google’s webmaster Tools voor de site die ik testte.

headless browser

Google crawlt nu met een headless browser

Uiteindelijk laat Google je daar toch ook alleen maar zien wat – ook – in hun beste belang is. Dus Webmaster Tools is ook geen ‘magic bullet’. Maar in ieder geval beter dan vele betaalde tools die allemaal claimen je te kunnen helpen, wat in veel gevallen simpelweg onzin is.

Uiteindelijk is SEO ook gewoon veel werk :). Hoewel ‘Moz‘ en andere tools die Google simuleren je wel een eind op weg kunnen helpen, de uiteindelijke analyse is aan jezelf. De precieze ‘magic sauce’ die Google toepast doen ze toch geen uitspraken over, dus dat vereist veel testen. En daarnaast verandert dit ook nog continue. Als simpele SEO’er kun je – na wat basis optimalisatie – je tijd dan meestal ook beter besteden aan gewoon goede content maken en het verder aan Google overlaten om dit te vinden. In plaats van allerlei ‘black hat’ technieken te gaan proberen, die ook nog tot een drop van je rank kunnen resulteren.

Hoe dan ook, de reden dat ik er nu toch een blogpost aan wijdt is omdat ik net een technische update vind van Google die toch redelijk revolutionair is. Twee weken oud. Dat is nog best nieuw toch? :P. Anyway, Google geeft aan dat ze vanaf deze maand eindelijk ‘headless browser’ gebruiken bij het crawlen.

Of laat ik hun eigen woorden maar (tegen ze?) gebruiken:

Today, as long as you’re not blocking Googlebot from crawling your JavaScript or CSS files, we are generally able to render and understand your web pages like modern browsers.

Daar zaten wij webdevelopers al sinds 2009 op te wachten. Dus goed nieuws toch? Maar – en dit is de grote MAAR – uit het testje wat ik net voor het lezen van dit bericht had gedaan kon ik juist concluderen dat ze dit NOG niet doen. Want daar was ik juist benieuwd naar.

Dat vond ik merkwaardig. Wat kon daar de reden voor zijn? Als gezegd doet Google zelf historisch gezien weinig uitspraken over hun precieze crawl technieken. Reden is dat alle black hatters dit dan gaan epxloiteren. Algemene uitspraken doen ze wel. In een artikel van een Google developer van afgelopen mei geven ze wat meer detail. Dit artikel is dus uit de tijd dat het headless browsen alleen nog maar aangekondig werd. En ze geven daarin niet meer reden dan dit:

  • Sometimes the JavaScript may be too complex or arcane for us to execute, in which case we can’t render the page fully and accurately.

In eerste instantie vind ik dit merkwaardig. Te complex? Als een ‘simpele’ browser er ook in slaagt om uiteindelijk de dynamische tekst tonen, dan kan Google’s geavanceerde crawl bot dit toch ook?

To arcane? In mijn geval betrof het wat functioliteit die grotendeels gebaseerd was op Google’s eigen Google Charts Javascript API. Dus die willen ze toch niet ‘to arcane’ noemen.

Toen ik hier verder over nadacht kon ik echter wel wat redenen bedenken. Het komt neer op asynchroniteit en schaalbaarheid. Het kan namelijk zo zijn dat:

  • De crawler maar een bepaalde maximale hoeveelheid Javascript uitvoert en indien er meer is, dat deze er dan niet eens aan begint. Hoewel de crawler ongetwijfeld geavanceerd is, crawl Google op zo’n grote schaal, dat ze wellicht het headless browsen op deze manier schaalbaar houden.
  • En/of het kan zijn dat indien er asynchrone calls worden gedaan in de Javascript, dat de crawler dan stopt. Hetzij meteen, hetzij na een aantal hops, hetzij er na een bepaalde timeout van enkele milliseconden geen reactie is. Omdat dan onzeker wordt hoe lang het duurt voordat de content klaar is, en de crawler niet opgehouden wil worden. Ook zou  Google via een statische analyse vooraf gedaan kunnen worden of de code asynchroon is of niet. In hun V8 engine (JIT) compilet Google immers ook al Javascript code ivm optimalisatie, dus die techniek hebben ze bij wijze van spreken uitgevonden.

Nou, al schrijvende ben ik ook alweer wat wijzer geworden. ‘ I think better when I write’. Om nog meer te achterhalen zou ik verdere testen moeten doen. Ik heb ook al even een vraag gesteld aan Google onder het artikel. Wellicht dat ze het zelf willen vertellen, hoewel ik maar nergens op reken ;).

Ik kan ook nog eens even de Google hoed verder over mijn hoofd zetten en terug in Google Webmaster Tools duiken. Dat is al weer meer dan een jaar geleden. Maar Google gaf dus in het gelinkte artikel van mei aan dat er een nieuwe tool zou komen voor analyse.

Als ik meer weet en tijd heb blog ik er wellicht over. Voor nu hoop ik dat een enkele lezer hier ook nog iets aan had. En kan ik mijn gedachtengang over een tijdje in ieder geval nog eens teruglezen. Reacties zijn ook welkom, hieronder!

Update 24-11-2015: N.a.v. een vraag nog even een update. Ik ben naderhand inderdaad nog in Google Webmaster Tools gedoken nav deze kwestie. Ik weet niet of de Mobile Test tool, de tool is die Google bedoelde, maar hiermee kreeg ik in ieder geval boven water dat de `corechart` library van Google zelf niet ingeladen wordt door de crawler. Dus dit is de ‘boosdoener’. Dit is een soort dynamische CDN. Wellicht dat Google deze zelf in een robots.txt heeft staan, of dat het komt door het dynamisch laden zoals ik eerder al stelde. Ik zou dus kunnen testen of het wel werkt als ik zelf deze .js download en host op de server (bv. via bower). Via iets als:

 

>bower install google-chart

Zie bijgevoegd (samengesteld) screenshot, deze geeft eigenlijk alles aan:

mobile-tester

Maar momenteel ben ik druk met andere zaken. En in geval ik er weer mee bezig ga, ga ik deze functionaliteit waarschijnlijk toch – ouderwets – naar de backend overhevelen, dat lost het ook op, en is qua security wat beter. Bij een vervolgopdracht komt er een en ander achter inlog te zitten.

Hoe log ik een bug?

Rudolph, is that a bug on your nose?

En iets over een rendier…

Mijn eerste blog

Per 30 maart ben ik gestart als zelfstandig ondernemer! Daar hoort natuurlijk ook een website bij én daarop een eigen blog. In mijn eerste blog post iets over hoe je nou een goede bug logged.

Hoe log ik een bug?

Ik ben nu al 10 jaar ontwikkelaar. Ontwikkelen is cool! Grofweg kun je al het ontwikkelwerk opdelen in twee categorieën
1) nieuwe funcionaliteit maken en
2) bestaande functionaliteit wijzigen/fixen.

Nieuwe functionaliteit maken vind ik toch het leukst en meest creatief, maar in de praktijk ben je vaak meer uren bezig bestaande functionaliteit te wijzigen. En het grootste deel daarvan bestaat weer uit bugs fixen. De term bug is afkomstig uit de beginjaren van de informatica, toen af en toe een echt insect nog echt in de grote computer kasten uit die tijd belandde en tot een rekenfout leidde. Maar tegenwoordig is de standaardterm voor een stukje programmeerwerk dat leidt tot een foutmelding of stuk ongewenst gedrag. Met de complexe systemen van tegenwoordig voorkom je niet dat er fouten in sluipen en het wordt door sommigen zelfs gevaarlijk genoemd om het idee te hebben dat je bugs geheel zou kunnen voorkomen tijdens het ontwikkelen.

Maar eenmaal gevonden moet een bug wel opgelost – of gefixed – worden. En om al die bugs beheersbaar te houden zijn er in de loop der jaren allerlei issue tracking systemen gekomen, en er komen er nog steeds nieuwe bij. Enkele van de bekendere zijn BugZilla, Jira, of het wat recentere GitHub issues. Het kan voor bakken geld (TFS) of gratiesch, dus elk zichzelf respecterend software moet zo´n bug database’ hebben, zoals Stack Overflow´s Joel Spolsky het noemt. Dit levert je weer een punt op in zijn befaamde Joel Test. En je krijgt nog een punt als bugfixing prio krijgt over de realisatie van nieuwe functionaliteit. Als Joel het zegt moet het wel waar zijn, dus bugfixing is de shit!

Hoewel bedrijven voor het maken van nieuwe functionaliteit vaak functioneel ontwerpers hebben, of requirements analisten en er ook allerlei meer of minder formele technieken bestaan om deze te beschrijven (use cases, user stories), wordt voor bugs nog vaak nog volstaan met slechts een vage one-liner als beschrijving: “Profielscherm geeft database fout” of “Grijstinten goed zetten”. Kortom `Doet het niet´, succces ermee!

Zo is een bug makkelijk gelogd, maar het gevolg is wel dat de ontwikkelaar die de bug moet gaan fixen zelf moet uitzoeken wat bedoeld wordt, hoe de bug te reproduceren en als dat allemaal lukt, hoe deze te fixen. Hij (/zij) komt dus vanzelf weer naar je toe. Terwijl je op het moment van loggen vaak zelf een veel beter idee hebt wat er mis ging. En als je dit niet, loont het de moeite dit even verder uit te zoeken. Dat levert later alleen maar winst op.

Met name in grotere teams is een goede bug beschrijving van zeer veel waarde. Zowel voor ontwikkelaars bij het reproduceren en oplossen ervan, als voor testers bij het hertesten na de fix. Een organisatie doet er daarom goed wat standaarden in te stellen voor een goede bugbeschrijving.

Voor testers is het goed loggen van bugs één belangrijke vaardigheid. Voor de ontwikkelaar is het ideaalbeeld om een ondubbelzinnige, makkelijk reproduceerbare bug te krijgen. Waar je geen verdere navraag meer hoeft te doen. Een aanzienlijk deel van bugs is met een goede omschrijving al voor meer dan 50% opgelost.

Ik geef geen volledig bug template, want deze zal toch per organisatie verschillen, maar hieronder beschrijf ik een aantal belangrijke componenten, die in de praktijk vaak ontbreken.

1. Verwachte uitkomst

Rudolph0

Een vaak vergeten onderdeel bij bugmeldingen is de verwachte uitkomst. Log altijd zowel de daadwerkelijk gekregen resultaat als de verwachte of gewenste resultaat! Wellicht vind je het logisch dat iedereen weet dat Rudolph’s neus rood is, maar sommige ontwikkelaars weten alleen dat hun auto in GTA rood is, en wie Rudolph is hebben ze geen idee van.

Enige uitzondering is eigenlijk als er een foutmelding/systeemmelding of stack trace optreedt, dan spreekt meer voor zich dat dit niet gewenst is. Maar het weglaten van gewenste uitkomst leidt soms ook tot een van de allermoeilijkst oplosbare en meest tijdvretende type bugs die er zijn: de bug die helemaal geen bug is…

2. ScreenshotRudolph2

Een beeld zegt meer dan 1000 woorden. Voeg bij elk beetje serieuze bug een screenshot toe. Dit bespaart je ellenlange beschrijvingen die vervolgens vaak toch niet begrepen worden. Vermeld wel in tekst op welke knop of welk andere actie direct voorafging aan de bug. Nog idealer is als je de fout in het screenshot kunt markeren met een rood blokje oid. Er zijn tegenwoordig allerlei tools voor zoals de Firefox plugin FireShot (is er ook voor Chrome en Internet Explorer). Ik gebruik zelf graag trusty old paint.net (open source bitmap editor).

Als je het kunt is het voor een beetje focus ook wel handig om irrelevante delen uit het screenshot te knippen. Maar let op: als het om een webapplicatie dan in het screenshot wel graag de ‘browser chrome’ opnemen (de randen met knoppen, adresbalk, etc.). Zo weet de ontwikkelaar namelijk meteen om welke browser het gaat. En kan eventueel hier ook nog een URL uitgehaald worden, Hoewel een URL als tekst (copy-paste) veel makkelijker is, zie onder.

3. ReproductiepadRudolph3

Voor de iets moeilijk bereikbare situaties, of die bugs die niet altijd optreden, maar alleen in heel specifieke situatie is het zeer aan te raden een reproductie pad te geven. Dit beschrijft stap voor stap welke stappen je moet zetten vanaf een bepaalde (beschreven) beginsituatie (bv. inloggen in een applicatie), om de bug opnieuw op te laten treden.

Het gebeurt regelmatig dat iemand die een reproductiepad opstelt, erachter komt dat een bug helemaal niet altijd optreedt. Het kost veel tijd, maar zet je Sherlock Holmes pad op, en spoor de foutsituatie nauwkeurig op. Vaak zegt dit ook al erg veel over de bug. Daarnaast kan je op deze manier soms ook een tijdelijke workaround vinden, zodat mensen op de werkvloer verder kunnen, zolang de bug nog niet is opgelost.

4. URL

Tot slot nog een vrij simpele, maar vaak vergeten: het adres van de pagina waarop de fout optrad. Dit is uiteraard alleen van toepassing als het een webapplicatie betreft, en ook als routing hierin van belang is. Maar dit kan een ontwikkelaar zeer veel tijd besparen, zeker als hij in één keer naar een foutsituatie toe kan klikken. En ook al lukt dit niet, en de gebruiker toch moet klikken, dan geeft het toch al wat context.

5. En verder

Merk op dat andere veelvoorkomende zaken nog niet besproken zijn. Er zijn zeker nog andere nuttige infovelden zoals type issue (bug of nieuwe feature), prioriteit van het issue (MoSCoW), gewenste oplevering/milestone waarin de bug gefixed of de versienummer van applicatie waarin de bug geconstanteerd is.

Tot slot

Het is níet de bedoeling dat bovenstaande punten het überhaupt loggen van een bug in de weg gaan staan. Als dat zo is, dan moeten deze eisen maar even naast je neergelegd worden. Maar je kunt dan in ieder geval bij het issue vermelden, bv. `geen tijd reproductiepad te speccen, vraag even mondeling na bij oppakken`.

Bijvoorbeeld van eindgebruikers kun je niet verwachten dat ze alle benodigde informatie aanleveren, en blijft gelden dat dat je beter een slecht omschreven bug kan inschieten, dan helemaal geen bug. De overige info moet dan later in de followup maar proberen te achterhalen. Maar het normale streven moet toch zijn een reproduceerbare, duidelijke bugbeschrijving mét screenshot.

Succes ermee!