En modul är logiskt grupperad funktionalitet. Bygger vi stora projekt i AngularJs finns det mycket att vinna på att ha en modulbaserad arkitektur. Delar vi upp applikationen i olika moduler får vi bättre ordning och reda genom att vi exempelvis kan kapsla in potentiella problem. Moduler ska ha få beroenden mellan varandra och kommunikation mellan moduler ska ske med hjälp av services eller events.
En moduluppdelad applikation blir enklare att testa eftersom vi kan mocka bort många beroenden. Dessutom blir det enklare att skala upp utvecklingsteamet eftersom utvecklare kan jobba ostört i olika moduler parallellt. Modulbaserad arkitektur kopplad med lite disciplin gör att vi kan säga hejdå till merge-konflikter. Jobbar man dessutom med git flow eller feature branches i sin källkodshantering kan man få en enkel och robust utvecklingsprocess.
Säg att vi ska bygga ett administrationsverktyg för en e-handel. I detta exempel skulle vi kunna ha nedan funktioner eller moduler.
För att uppnå störst inkapsling och separering är det bra att utveckla varje modul i ett separat projekt. Detta för med sig extra arbete så en pragmatisk mellanväg är att ha alla moduler i samma projekt, åtminstone tills projektet når en viss storlek. Om projektet blir stort kan man bryta ut modulerna till egna projekt och publicera som egna paket, exempelvis hos npm.
Sortera inte ditt projekt efter filtyp utan efter funktion eller modul. I andra fall är det vanligt att sortera efter typ, ex C# MVC, men i AngularJS ska en modul vara grupperad tillsammans i projektet. Du bryter mot inkapslingen om du sorterar projektet efter filtyp samt att det blir svårare att hitta.
Helst ska en modul inte ha några kunskaper om andra moduler, t.ex. vilka controllers eller vyer den innehåller. Av denna anledning faller det naturligt att varje modul ska definiera sin egen navigering. Med fördel kan varje modul ha en definitionsfil och en konfigurationsfil, lägg navigeringen i konfigurationsfilen.
För att undvika konflikter mellan moduler kan varje modul ha ett eget prefix i URL-adressen.
Ofta behöver modulerna i stora projekt dela data. Kommunikation mellan modulerna sköts genom antingen events eller gemensamma services. Alla moduler kommer att dela $rootScope varför det är enkelt att använda events. Gemensamma services kan brytas ut och läggas i en egen modul, typ admin.common.
Gör aldrig data eller funktioner globala för att kommunicera med en annan modul.
Att gå från en vy i en modul till en vy i en annan modul kräver i regel att man vet vilka vyer eller states den andra modulen har. Länken måste vara explicit. Detta bryter mot inkapslingen.
<a ui-sref="inventory.list">List Inventory</a>
Här kan man tänka sig olika lösningar med t.ex. "service locator pattern" för att generera länken när applikationen kör. Länken kan exempelvis genereras olika beroende på vilka moduler som är laddade osv. Detta medför dock komplexitet och har i min erfarenhet inte tillfört värde i något projekt. Mitt råd: Var pragmatisk och börja med explicita länkar som i exemplet ovan.
I bilagan till denna artikel går det att ladda ned ett projekt med exempelkod.