Fram till för bara ett halvår sedan har jag inte haft en tanke på att skriva ”hållbar kod”. Jag placerade html i html-filerna, css i css-filen, javascript i javascriptfilen — och om jag kände för det skrev jag en liten kommentar någonstans. Det räcker väl? Fungerade det och såg bra ut i webbläsaren så har jag ju dragit mitt strå till stacken. Eller hur? Det var ju aldrig någon som skulle arbeta vidare på det jag gjort ändå — och om det nu var det, så var det ju deras problem om de inte var smarta nog att förstå min kod. 

Faktum är att när jag tittar tillbaka på gammal kod så förstår jag ofta inte ens själv vad jag tänkte på när jag skrev den. I den här artikeln ska vi titta närmare på ett designmönster som innebär att vi strukturera vår javascript i fristående moduler. Tanken är att det ska underlätta vårt arbete som utvecklare, och förhoppningsvis förenkla arbetet för nästa person som tar över facklan och fortsätter bygga på det vi påbörjat.

Varför bör vi tänka på hur vi strukturerar vår kod?

Första gången jag programmerade i javascript skrev jag allt i kronologisk ordning, helt utan tanke på att skapa en logisk struktur— när jag kom på att något behövde läggas till, så la jag till det. Det resulterade i ett långt och ostrukturerat dokument med ett virrvarr av metoder och anrop till olika element i DOMen, det som många utvecklare kallar spagettikod (Osmani, 2012C). Att sedan gå tillbaka och arbeta i koden för att till exempel lägga till, ta bort eller byta ut funktionalitet blev en mardröm eftersom allt på ett eller annat sätt var beroende av vartannat. Det var ungefär som att underhålla ett korthus; togs en del bort så rasade hela konstruktionen.

Sommaren 2014 spenderade jag mycket tid med Node.js och blev förälskad  i dess modulära struktur. Node.js gör det enkelt att innesluta relaterad kod i moduler, som med fördel kan existera i separata filer. Det är sedan smidigt att hämta de delar som behövs, när de behövs. Koden blir lätt att underhålla, överskådlig, och det är lätt att lägga till och ta bort moduler. Det minskar också risken att hela applikationen havererar på grund av en bugg i en av modulerna.

Varför är det en bra idé att bygga modulärt?

Med en modulär struktur kan individuella komponenter återanvändas både inom applikationen och i andra projekt. Låt oss säga att du har byggt en applikation för ett konsultföretag. Applikation som gör det möjligt för konsulterna att kommunicera inom ett projekt. De kan bland annat dela allmän information (projektstatus, utgifter etc.), boka möten och dela scheman. Applikationen innehåller också bland annat en chattmodul där projektmedlemmarna kan kommunicera i realtid. Chattmodulen är vid uppstart kollapsad och är enbart representerad av en ikon. Den använder därför inga systemresurser förrän användaren specifikt talar om för applikationen att chattmodulen ska aktiveras. Att ladda moduler dynamiskt på det här sättet ska idealiskt sett ske utan att påverka resten av applikationen negativt (Osmani, 2012A). Eftersom du har konstruerat chattmodulen helt fristående är det också lätt för dig att återanvända den i nya projekt, optimalt utan att behöva göra några förändringar i koden. Beroende på hur komplex chattmodulen är, kan den i sin tur bestå av flertalet mindre sub-moduler. En sub-modul kanske till exempel enbart hanterar emoticons, och återanvänds på flera andra ställen i applikationen.

 The secret to building large apps is never build large apps. Break your applications into small pieces. Then, assemble those testable, bite-sized pieces into your big application

-Justin Meyer, author JavaScriptMVC (Osmani, 2012A)

Att bygga i moduler underlättar också för flera utvecklare att arbeta på samma projekt samtidigt. Eftersom alla moduler och deras komponenter är fristående och skyddade från andra moduler, kan arbete utföras på flera individuella delar samtidigt. Risken för konflikter i utvecklarnas arbete blir minimal.

Modulära javascript-applikationer

Generellt sett så innebär en modulär struktur att applikationen byggs i flera helt fristående delar, det vill säga med så kallade lösa bindningar (loose coupling) (Osmani, 2012B). Att applikationen byggs med lösa bindningar innebär att alla komponenter är helt självständiga och kan köras och testas individuellt.

 The more tied components are to each other, the less reusable they will be, and the more difficult it becomes to make changes to one without accidentally affecting another –Rebecca Murphey, author of jQuery Fundamentals (Osmani, 2012A)

Genom att programmera ett API (Application Programming Interface) skapar vi ett programmeringsgränssnitt som exponerar utvalda metoder och variabler för resten av applikationen. Det möjliggör kommunikation med modulen så att vi till exempel kan förse den med data eller hämta vissa värden. Allt annat hålls ”privat” inom modulen.

En modul ska som tidigare konstaterat inte vara beroende av en annan modul för att kunna fungera. Modulerna kommunicerar därför inte med varandra utan bara med den så kallade medlaren (the Mediator) (Stone, 2009). Medlaren fungerar som en central punkt i applikationen och interagerar med  modulerna (Osmani 2014).

 The mediator pattern is best introduced with a simple analogy – think of your typical airport traffic control. The tower handles what planes can take off and land because all communications are done from the planes to the control tower, rather than from plane-to-plane. A centralized controller is key to the success of this system and that’s really what a mediator is. (Osmani, 2012A).

Säg att Modul1 talar om för medlaren att något måste göras. Då ”startar” medlaren de moduler som behövs för att genomföra uppgiften. Modul2 genomför uppgiften som Modul1 begärde och talar om för medlaren att uppgiften är slutförd. Under tiden har Modul3 startats av medlaren och sparat alla resultat i en logg. Under hela processen sker ingen kontakt direkt mellan modulerna. Om Modul3 skulle sluta fungera skulle medlaren hypotetiskt sett kunna pausa uppgiften, starta om Modul3, och sedan starta uppgiften igen utan att påverka systemet i helhet (Osmani, 2012A).

Slutord

Det finns många olika designmönster att välja mellan när det kommer till programmering. Först och främst handlar det om att hitta ett som känns logiskt för dig, och dina medprogrammerare. Det kan verka som en stor tidsinvestering att sätta sig in i ett designmönster, men förhoppningsvis är det värt det i slutändan.

Det här var en introduktion till javascriptmoduler i teorin. Att bygga modulära javascriptapplikationer i praktiken får blir en annan artikel. För den som vill lära sig mer om det nu på en gång kan jag rekommendera att titta på ramverk som Browserify, Node.js och Require.js.

Källor

Kashyap, V. (2010). What Is An API & What Are They Good For? [Technology Explained]. [online] MakeUseOf. Available at: http://www.makeuseof.com/tag/api-good-technology-explained/ [Accessed 23 Nov. 2014].

Osmani, A. (2014). Learning JavaScript Design Patterns. [online] Addyosmani.com. Available at: http://addyosmani.com/resources/essentialjsdesignpatterns/book/ [Accessed 23 Nov. 2014].

Osmani, A. (2012C). Journey Through The JavaScript MVC Jungle – Smashing Magazine. [online] Smashing Magazine. Available at: http://www.smashingmagazine.com/2012/07/27/journey-through-the-javascript-mvc-jungle/ [Accessed 23 Nov. 2014].

Osmani, A. (2012A). Patterns For Large-Scale JavaScript Application Architecture. [online] Addyosmani.com. Available at: http://addyosmani.com/largescalejavascript/ [Accessed 23 Nov. 2014].

Osmani, A. (2012B). Writing Modular JavaScript With AMD, CommonJS & ES Harmony. [online] Addyosmani.com. Available at: http://addyosmani.com/writing-modular-js/ [Accessed 23 Nov. 2014].

Stone, H. (2009). JavaScript Design Patterns: Mediator : arguments.callee. [online] Arguments.callee.info. Available at: http://arguments.callee.info/2009/05/18/javascript-design-patterns–mediator/ [Accessed 23 Nov. 2014].