This is an archived copy of all my blog posts which is irregularly updated.
  • MSIL injection met PostSharp

    Wanneer je manager een nieuwe techniek ten strengste verbied met als argument 'we snappen je code normaal al niet, dit maakt het alleen maar erger' weet je dat je goud in handen hebt. Voor een eigen projectje om vals te spelen met Football Manager (waar ik later absoluut nog eens terug kom) had ik globaal de volgende situatie:

    public byte CurrentAbility
    {
        get {
            if (_mode == DbMode.Cached) {
                // in cached mode, hebben we een byte-array met alle waardes
                return _bytes[Offsets.CurrentAbility];
            } else {
                // anders lezen we via een helper-method
                return ProcessManager.ReadByte(_address + Offsets.CurrentAbility);
            }
        }
        set {
            // zelfde soort code voor de setter
        }
    }

    Leuk, neat, en vrij goed te lezen; probleem alleen dat ik een paar honderd properties heb, met een stuk of zeven verschillende types. Te veel werk. En aangezien je in eigen projecten toch helemaal los mocht gaan, leek een oplossing op basis van AOP me veel leuker. Nieuwe situatie:

    [FMEntity(Offsets.CurrentAbility)]
    public byte CurrentAbility { get; set; }

    Bovenstaande is best eenvoudig werkend te krijgen met PostSharp, een framework voor Aspect Oriented Programming in .NET. Een eenvoudige implementatie van bovenstaande is iets als:

    public class FMEntityAttribute : LocationInterceptionAspect
    {
        public FMEntityAttribute (int offset) {
            // doe wat
        }
        
        public override void OnGetValue( LocationInterceptionArgs args ) {
            if (args.Instance is byte) {
                // doe byte lezen enzo
            }
        }
        
        public override void OnSetValue( LocationInterceptionArgs args ) {
            // ongeveer hetzelfde
        }
    }

    Je kunt nu alle logica die toch steeds hetzelfde is, eenvoudig webabstraheren in een aparte file. Maar... té traag. In mijn geval werd het bepalen van de rating voor spelers ruim tien keer zo traag; door alle overhead. Oplossing? Zelf MSIL injecten!

    Continue reading »

  • Beeldmateriaal: funda 10 jaar!

    http://www.funda.nl/media/10597710/funda%20anno%202001.png
    Tien jaar bestaat funda alweer, en in al die jaren is er vrij veel veranderd. Het originele functioneel ontwerp voor héél funda telde bijvoorbeeld 9 hoofdstukken (inclusief 360 graden foto's!); 10 jaar later telt het FO voor alleen de 360 foto's maar liefst 23 hoofdstukken! Niet voor niets natuurlijk, want die tien jaar ontwikkeling; en die honderden pagina's aan extra FO's hebben tot veel moois geleid (ik schrijf hier elke dag een pagina over vol!). De afbeeldingen die hier eerder stonden zijn op verzoek verwijderd, dus derhalve een overzicht van 10 jaar funda aan de hand van de homepage.

    Continue reading »

  • Javascript herschrijven naar een jQuery plugin

    Wanneer het op 'normale' backendcode aankomt is refactoring en het opnieuw schrijven van delen code welhaast een routineklus geworden. JavaScript is daarin wat lastiger; scoping is minder transparant, dus je breekt eenvoudig bestaande code die wellicht niets te maken heeft met jouw deel; en de flexibiliteit kan tegen je gaan werken. Vandaar een artikel over de wondere wereld van het herschrijven van de JavaScript voor de footer op funda!
    http://www.100procentjan.nl/tweakers/viafunda.png

    Continue reading »

  • Bouw eens een API met WCF, deel 3: Domain entities converteren naar API entities

    De domain entities die je zelf gebruikt op je site zijn niet noodzakelijk ook de entities die je via je API wil communiceren. Dit kan alleen naamgeving zijn, maar ook het uitsluiten van bepaalde velden of het toevoegen van afgeleide velden. Al snel krijg je code als:

    public ApiObject Convert(DomainObject domain) {
         ApiObject api = new ApiObject();
         api.Adres = domain.Adres;
         api.Huisnummer = domain.Huisnummer;
         if(domain.Makelaar) {
               api.MakelaarNummer = domain.Makelaar.Id;
         }
    }

    Niet alleen veel werk (geloof me, ik heb op mijn 19e duizenden regels van dit soort code zitten kloppen), maar door alle boilerplate ook nog eens onoverzichtelijk (imagine bovenstaand fragment maar dan met 200 properties!). Goed moment voor expression trees om dit soort code on-the-fly te genereren.

    Continue reading »

  • Bouw eens een API met WCF, deel 2: Autorisatie

    Bij een API is toegangsbeperking een fijn idee, zo voorkom je dat bezoekers je hele platform platleggen of kan je contractueel vastgestelde beperkingen afdwingen. Standaardautorisatie zou je kunnen doen via sessies, op IP basis of via een Key. Sessies vallen per definitie af, omdat de gemiddelde API client helemaal geen sessie-informatie kan of wil doorsturen. Op IP basis zou prima kunnen om het maximaal aantal requests te kunnen monitoren, maar je kunt hiermee geen restricties op de API plaatsen. Vandaar dat we hebben gekozen voor een systeem op basis van een key.

    Database
    In onze database hebben we een heel simpele structuur met een n-n relatie tussen de Users en de Rights.

    Users
    --------------------------------------
    Id  | Key               | Name
    1   | abcde1234af32     | Jan's Mobile Client
    Rights
    ---------------------------------------
    Id  | Description
    101 | Opvragen koopaanbod
    UserRights
    ---------------------------------------
    UserId  | RightId
    1       | 101

    Continue reading »

  • Bouw eens een API met WCF, deel 1

    Er komt een moment in de geschiedenis van elke contentleverancier dat er de vraag komt om je content anders te gaan presenteren. Van je ‘main’ platform naar bijvoorbeeld mobiel.
    http://www.100procentjan.nl/tweakers/api1.png
    Probleem: bij een website heb je één centrale server waar je database op draait, en waar je met je favoriete toolkit tegenaan kan praten. Bij een mobiele applicatie is het iets lastiger om een database van 12 GB mee te leveren. Ergo: tijd om je content beschikbaar te maken voor externe leveranciers via een API.

    Continue reading »

  • Waarom je nooit mag toegeven dat je Ruby on Rails hebt bestudeerd

    Vanochtend gevonden op mijn bureau n.a.v. mijn comment gisteren met de complimenten van een niet nader te noemen collega die mij al weken probeert lid te maken van de RoR fanclub.

    Continue reading »

  • Rails' respond_to in ASP.NET MVC

    In Ruby on Rails is het mogelijk om met respond_to een actie beschikbaar te maken in andere formaten dan HTML met één regel. Pretty neat, omdat je je code zo zonder moeite via verschillende interfaces kan gebruiken.

    respond_to do |format|
      format.html
      format.xml  { render :xml => @huis }
      format.json { render :json => @huis }
    end

    In ASP.NET MVC 2 is er niet standaard zo'n oplossing, maar doordat MVC zo pluggable is is deze wel eenvoudig toe te voegen.

    Continue reading »

  • Solr, deel 1: Introductie tot faceted search

    Alle huizen op funda staan netjes opgeslagen in een SQL Server database. Normaal gesproken best praktisch, maar niet flexibel genoeg om al onze wensen eenvoudig te vervullen. Vandaar de overstap naar een zoekplatform dat hier wél voor geoptimaliseerd is. Vandaag deel 1 in een technische serie over de overgang naar Solr.

    Bij onze zoektocht naar nieuwe software is het van belang dat deze snel is, want we serveren tijdens een beetje drukte makkelijk meer dan 300 pageviews per seconde. Daar ligt ook meteen het goede nieuws: Solr is blazingly fast! Op één instance haalden we al een performance van 1.000 req/s. En dat is niet alleen zoeken, maar inclusief het converteren van en naar .NET code. En het mooie is; het integreren binnen een bestaande .NET omgeving is helemaal niet zo lastig!

    Continue reading »

  • Javascript, state van snel opvolgende AJAX requests bijhouden (?)

    Tijdens het productiewaardig krijgen van de Javascript van de nieuwe zoeksuggesties stuitte ik op een probleem waarin de gebruiker snel achter elkaar doortypt:

    amst            (request #1)
    amste            (request #2)
    amster            (request #3)

    Geen probleem zolang de requests allemaal even lang duren. Maar wanneer deze terugkomen in de volgorde:

    #1
    #3
    #2

    staat er verkeerde data in de suggesties.

    Continue reading »