GeekHub vNext - En spade prøver at implementere CQRS

Se et, hvad der nok er en meget forkert, førsøg på at implementere CQRS i Geekhub vNext.

Read more

GeekHub vNext - Implementering af Widget featuren

Jeg har lavet en lille video, for at teste Google Hangouts. Den viser en simpel implementering af en feature til Geekhub vNext, som er implementeret i C#.

Bemærk at den er meget low-key :)

Read more

Anden dag med NodeJS - lidt noter

Så jeg fik arbejdet lidt videre på min applikation idag. Stadig ingen ide hvad den ender med, så jeg begyndte stille og roligt at lave nogle entries, og kalde det for en Journal. Pænt generisk tænkte jeg.

Jeg fik roddet med at man kunne have en user, som havde sin egen URL-root, f.eks.: awesomeapp.com/deldy Under deldy bliver der så læst nogle layout parametre ind, som gør at man kan styre layoutet. Ligenu er det kun en titel og en intro - men ideen er at man kan overstyre forskellige ting. En meget simpel form for CMS kan man kalde det, hvis man er en smule naiv omkring hvad et CMS består af :)

Dette er mine noter fra dag 2-ish:

Express Middleware

Jeg vidste at jeg ved en del actions fik brug for at loade en "bruger", og hans layout parametre. Man kunne selvfølgelig kalde en funktion i alle mine actions som ville indlæse disse værdier, men efter at Google efter en before_filter i express, så faldt svaret på middleware.

Middleware er sådan et ikke andet end hvad et HttpModule er i .NET - en simpel funktion som kører før dit rigtigt request. Her er der rig mulighed for f.eks. at loade noget data, og ligge det et sted så dine senere actions har adgang til det.

I express.js så kan man nemt lave en route, som kører på alle requests der matcher et pattern:

app.all('/:user/*', middleware.loadUser, middleware.loadLayout)

:user er mine variable, som så fanger f.eks. "deldy". Jeg har 2 stk middleware: loadUser og loadLayout. LoadUser sætte bare en user på mit request, så resten af requested kan få fat i dem. LoadLayout læser en masse key/value entries fra databasen og konvertere dem til et layout objekt, så mit view kan have adgang til den. Dette bringer mig frem til det første nye "library-of-the-day":

Underscore.js

Underscore er en hel bunke utility funktioner som f.eks. hjælper dig med at lave LINQ-agtige ting på arrays osv. De funktioner jeg brugte idag var _.map, _.object og _.extend Dette lib er også ganske brugbart i din client-side JavaScript.

Map
Map er hvad der svarer til Select i LINQ - du giver den listen, og den funktion som laver listen om til en anden liste. _.map(list, function(item) { return item + "other-stuff"});

Object
Object er en simpel måde at lave en liste af arrays (En liste med en liste af [key,value] arrays) om til et objekt. Dette blev brugt sammen med map til at lave et result fra databasen om til et objekt. Her er en lille hjælpe funktion som gør dette let. Den bruger både Map og Object:

function arrayToObject(list, keyField, valueField) {
    keyField = keyField || "key";
    valueField = valueField || "value";

    var mapped = _.map(list, function(x) {
        return [x[keyField], x[valueField]];
    });

    return _.object(mapped);
}

Extend
Extend hjælper med at lave en merge mellem to objekter. Det jeg skulle lave var at gøre det muligt at have nogle default layout parametre, og så gøre så en user kunne overskrive eller udvide de værdier som var tilgængelige. Extend hjælper med dette:

var layout = defaultLayout(user);
layout = _.extend(layout, userLayout);

Hvis layout have en key A, og userLayout også have en key A, så ville værdien for userLayout overstyre værdien fra layout - lige som vi ønsker. Nifty lille funktion, som findes i mange libs rundt omkring.

Moment.js

Den sidste ting jeg arbjedet med, var at vise en liste af entries. Selvfølgelig skulle der også vises hvornår de var oprettet. Her kommer vi over til hvordan vi formatere datoer i JavaScript. Her valgte jeg Moment.js - For at lave en javascript dato om til en string, gjorde jeg bare følgende:

return moment(date).format(format);

Mit format var så bare "DD/MM/YYYY", men den kan både parse og formatere datoer i alle mulige sprog. Et rigtigt godt bibliotek. Dette bibliotek er også rart i client-side JavaScript.

Express 'View-Helpers'

Du har rig mulighed for at lave hjælpefunktioner i Express - de kalder det bare for app.locals. Hvis du sætter app.locals, så er der adgang til disse i dit view:

app.locals({
    formatDate: function(date, format) {
        return moment(date).format(format);
    }
})

Dette giver mulighed for at kalde formatDate i dit view. Dejligt let.

Afslutning

Jeg synes det var en sjov dag idag. Jeg havde lidt mere held med mine ting idag, og jeg synes jeg fandt nogle gode og lette løsninger til nogle problemstillinger. Koden ligger på GitHub, hvis du gerne vil se hvad det er blevet til.

Read more

Første dag med NodeJS - lidt noter

Bemærk denne post ikke er en tutorial, men mere en samling af mine erfaringer

En stille og rolig søndag, gik jeg i gang med at rode med NodeJS.

Mest for at blive epic til JavaScript, men også fordi det er sjovt at lære. Jeg har kigget ganske lidt på det før, men tænkte jeg skulle give det et forsøg til.

Jeg startede med at bruge CoffeeScript, men pga. min meget lille erfaring med CoffeeScript, så fandt jeg hurtigt ud af at jeg prøvede at lære for meget på en gang. Dette var også grunden til at jeg valgte at bruge en normal database til mit projekt i stedet for at bruge MongoDB eller lign.

Databasen er så blevet PostgresSQL - mest fordi det lige passer sammen med Heroku, som nok er den platform det færdige projekt kommer ud på. Hvad er så det færdige projekt spørger du? No clue, jeg kom aldrig langt nok denne dag til at finde ud af det.

Denne blog post beskriver nogle af de ting jeg oplevede, samt nogle noter som måske kan hjælpe andre, og ikke mindst hjælpe mig i fremtiden.

Installation

Det er meget nemt at installere NodeJS, hent en installer på nettet og kør programmet.

NPM

NodeJS bruger et commandline tool til at hente "plugins" eller biblioteker med. Det hedder NPM, og skal køres via din Terminal el. cmd. Det der er vigtigt lige at forstå det er at dit projekt skal have en package.json fil, som beskriver dit projekt, og ville pakker den har behov for. Den ser nogenlunde sådan her ud:

{
  "name": "application-name",
  "version": "0.0.1",
  "private": true,
  "scripts": {
    "start": "node app.js"
  },
  "dependencies": {
    "express": "3.4.8",
    "jade": "*"
  }
}

Du kører bare denne kommando for at installere en pakke. Bemærk --save flaget som sørger for at opdatere din ´package.json´ fil:

npm install pakke --save

Express

Jeg har valgt at bruge Express som web framework. Ingen ide om det er det bedste, men det virker relativt simpelt. Du skal installere det i dit "global"-scope med NPM. Det gør at du kan bruge ´express´ programmet til at oprette din projektskabelon

npm install express -g

Derefter kører du bare denne kommando i en mappe, hvor du har dine projekter:

express projektnavn

Nu er der en mappe der hedder projektnavn hvor din applikation ligger i. Der ligger en ´app.js´ fil med din applikation. Jeg vil ikke gå mere i detaljer med express i denne post.

Postgress

Der findes et hav er data access libraries til NodeJS. Jeg valgte bare at køre på metallet, og bruge Postgres direkte med ´pg´ for ikke at have for mange lag. Ingen har taget skade er noget SQL. Jeg brugte Postgress.app til Mac OS, så det skal bare installeres, startes.
En lille note omkring at forbinde med pgAdmin til din Postgress.app database, så er ´username´ dit brugernavn til din computer, og kodeordet er blankt.
NodeJS modulet skal installeres i projektet således:

npm install pg --save

Der findes et fint codesample på deres GitHub repo. En lille note er at din connectionstring er følgende når du bruger postgress.app: ´postgres://localhost/databasenavn´

Promise Library (Q)

En af de udfordringer med NodeJS er at det meget asynkront, så jeg ledte efter et Promise library, for at gøre det lidt lettere. Jeg fandt Q. Jeg tænkte det var let nok, men jeg må indrømme at jeg nok skulle have ventet lidt med at introducere det. Q's dokumentation var lidt svær for mig at forstå. Her er lidt tips til den:

var d = Q.defer() // Laver et objekt som du kan kalde, resolve eller reject på.

d.resolve("Dit result");
d.reject("Der skete en fejl");

return d.promise(); // Laver et objekt til din kalder, som de kan kalde then og fail på.

Sådan her bruger du din defer:

myAsyncFunc().then(function(result) { console.log(result) }).fail(function(err) { console.log(err) })

Du kan også retunere noget i din ´then´, og så lave en ny then efterfølgende, hvor dens parameter så er det du retunerede i din første then.

Hvis du har en liste af defers som du vil vente på, så kan du bruge Q.all:

var calls = [myAsyncFunc(), myAsyncFunc()];
Q.all(calls).then(function(results) { console.log(results) }) // Dine resultater kommer som et array.

Afslutning

Dette var hvad jeg nåede første dag. Jeg fik skrevet lidt kode til at hente konfigurationer fra databasen i et key,value format, samt indsætte nye værdier. Alt andet tid brugte jeg på at fejle hårdt. Jeg synes NodeJS er svært at komme i gang med, især pga. alt er async, men jeg håber jeg ser lyset når jeg kommer længere. :)

Read more

Når JavaScript bliver et problem

Når en web applikation rammer en bestemt størrelse, og kører i produktion, så kan mange løsninger nå til et punkt, hvor udviklerne generelt begynder at hade at ændre ved JavaScript'en. JQuery biblioteket bliver aldrig opdateret, og der ligger sikkert stadig et plugin til at håndtere watermarks i tekstfelter, selvom dette nu er standard i HTML5. Ingen tør bruge nogle nye biblioteker, og hvis en person gør, så bliver han evigt hadet af resten af teamet, fordi det nye bibliotek lige pludselig indførte en bug et sted man ikke forudså.

Men hvorfor er det så at vi kommer til dette punkt? Efter at have skiftet arbejde, til et nyt sted, med nye practices om hvordan de inkludere JavaScript, så tror jeg at jeg er kommet tættere på en tidligere, for mig, ukendt årsag.

På løsninger jeg tidligere har været med til at lave, var vi rimelig nazi med JavaScript. Det skulle bundles og minifies. Typisk resulterede dette i en stor hairball af JavaScript, som betød af alle sider brugte det samme JavaScript. Inkluderede du lige KnockoutJS på den side der? Sig velkommen til KnockoutJS på alle sider. (Tro mig, jeg har været en god drivkraft i den udvikling, og har ment at det var best practice.)

Målet er mindre requests, som skulle gøre din side hurtigere. Denne store hairball af JavaScript skal så parset hver gang du besøger en side, men det glemmer man typisk at tænke på. Dette vil betyde at KnockoutJS nu bruger CPU-cycler på at bliver parset hos klienten ved hvert side besøg. Gæt engang hvorfor en side er kan virke tung på en mobillos, selvom den har 4G/LTE – sikkert pga. den er CPU tung.

Ved at bruge den samme bundle over det hele, så laver du noget så autonomt som JavaScript om til noget der svarer til projekt-referencer. Hele din applikation er nu lige pludselig afhængig af det eksterne bibliotek, og nu skal alle enes om at bruge den samme version, hvilket gør at du ikke kan opdatere stille og roligt. Du skal tage det store spring, hvilket nok vil betyde at du helst ikke laver springet, før der er en kritisk bug i 3. parts biblioteket. Husk nu, at frontend kode er der hvor der sker mest udvikling, så 3. parts biblioteker skal opdateres, hvis du vil understøtte fremtiden. Så hvis det gør ’ondt’ at opdatere din JavaScript dependency, så løs problemet. Hvad laver dette problem? Din holdning til at du skal have det samme JavaScript på tværs af din applikation.

Ved at bruge den samme bundle over det hele, så har du også åbnet op for at en syntaksfejl i dit JavaScript kan ødelægge store dele af din applikation. Jeg er ikke ekspert på JavaScript parsere, så jeg tror at hvis du scoper nogle ting smart, så kan du isolere dine områder i dit JS, så kun et område går ned. Realiteten i meget JavaScript-kode er dog at folk stadig ikke har helt styr på god JavaScript skik. Jeg har oplevet eksempler på hvor JavaScript syntax-fejl i helt andre områder af et site har betydet at du f.eks. ikke kunne logge ind. Nu kan du selvfølgelig sige at der er noget helt galt, hvis man får syntax-fejl helt ud i produktion. Jeg har dog set det ske, og hvis sådan noget her sker, så kan du tro, at programmøren ikke har lyst til at rode med JavaScript det næste stykke tid. Hvis I har en kultur hvor fejl bliver blamet, og hvor ikke-programmører bliver ”bekymret”, så kan resultatet sikkert blive at folk lige skal huske at teste login funktionaliteten før og efter de deployer, og alle lover højt og helligt at være mere forsigtig. Episode 2: Return of the Syntax-Error.
(Tro mig, jeg har været en væsentlig drivkraft til dette pattern af ”pas-bedre-på-og-test-mere-manuelt-før-deploy-mønster”.) Hvad laver dette problem? Din holdning til at du skal have det samme JavaScript på tværs af din applikation, og her er det også vigtigt at det bliver bundlet, da det kan ødelægge resten af filen (og måske lidt at du ikke har frontend-testing)

På mit nye arbejdsplads findes dette problem ikke rigtigt. Jo, der er da gamle versioner af JQuery og en syntax-fejl sniger sig sikkert også ind i ny og næ. Forskellen er at løsningen har en del år på bagen, og derfor bruger den slet ikke bundling, og alle JavaScripts er inkluderet på side niveau, bortset fra kernen af JavaScript (som JQuery, og funktioner i layoutet). Hver side kan bestemme dens version af JQuery, og måske også andre eksterne biblioteker. Så vil du gerne bruge version 2 af JQuery – go ahead, brug det på din side. Har du lidt tid til overs? Tag og skift en side til den nye version af JQuery, og test den stille og roligt igennem. Skal du bruge KnockoutJS på din side? Den inkludere du bare på din side. Det er totalt oldschool, og det er ikke særligt optimeret, men det har overrasket mig hvilke indvirkning det har på programmørens holding til at opdatere JavaScript.
Selvom det er rent backend, og returning users, så står vi overfor at vi gerne vil have lidt bundling på sitet, bare fordi det giver mening nogen steder, og at der nogen gange er nogle logiske sæt af JavaScript som hører sammen. Det I kan være helt sikker på at vi ikke gør, er at lave en stor hairball af alt JavaScript på sitet, i en bundle to rule them all.

Så tænk over om du kan genkende nogle af disse problemer, hvis du kan, så se på om I kan splitte jeres JavaScript lidt op. Læg f.eks. ikke JQuery i din bundle, men brug i stedet en CDN med en lokal fallback. Lad være med at have nogle store utility biblioteker hvor syntax-fejl kan snige sig ind, og som alle skal bruge.

Ligesom med mange andre ting ved programmering: Hvis noget gør ondt, så gør mere af det, eller noget ved det.

Read more

Next page