Organisk utveckling


Introduktion

Jag arbetade som grafisk formgivare för några år sedan och ett gemensamt problem som jag skulle komma på var att välja färgscheman för nya projekt. En av mina kollegor sa, "Välj bara ett fint foto och ta färgar därifrån". Denna teknik fungerar bra eftersom bilder ger dig en naturlig kombination av färger. Så tänkte jag: "Varför inte överföra samma begrepp till mitt arbete som kodare?". Och det här är där ekologiskt kommer in att spela. När jag först introducerades till ekologiska blev jag förvånad över hur enkelt det var och samtidigt hur flexibelt det är. Slutligen hade jag något som uppmuntrar till modulär programmering, det är lika användbart som MVC-mönstret, och det är ett bra verktyg för arkitektur.


Konceptet

Som du kanske har gissat är det organiska konceptet biologiskt baserat. Din huvudansökan fungerar som en Cell, som har a Membran och a Nucleus. Men det verkliga jobbet hos en cell görs av organeller, vilka kommunicerar mellan varandra med Kemikalier. Naturligtvis är elementen och processerna i Organic inte 100% identiska med verkliga celler, men de är ganska nära. Nu vet jag att det låter galet, men när du börjar arbeta med det ser du hur enkelt och naturligt det här sättet kan vara när du applicerar det på dina appar.


Hämta Organisk

Organisk distribueras som en nodmodul. Så du borde ha NodeJS redan installerad. Om du inte gör det, gå till nodejs.org och ta den senaste versionen för ditt operativsystem. Din package.json filen ska se så här ut:

"namn": "OrganicDevelopment", "version": "0.0.0", "description": "Organisk utveckling", "beroenden": "organic": "0.0.11", "author": "Your Namn här "

Springa npm installera i samma katalog och chefen hämtar de nödvändiga filerna. Kärnan i organiska är faktiskt ganska liten. Den innehåller endast definitionen av huvudelementen - Cell, Nucleus, Membrane, Plasma, Organelle, Chemical och DNA. Självklart kommer det med några tester, men det är ett litet paket totalt sett. Detta hjälper till att göra det lätt att lära sig och börja utvecklas med nästan omedelbart.


Exemplet

För denna artikel bestämde jag mig för att skapa en enkel webbplats med bara kärnan i organiska. Källkoden kan laddas ned längst upp i den här artikeln om du vill följa med. Jag tycker att det här provet är det bästa sättet att presentera det här nya mönstret. Sidan innehåller två sidor - Hem och Handla om. Här är en skärmdump av webbplatsen:

Appen innehåller två knappar som länkar till de två olika sidorna. De Handla om sidan har bara lite mer text än Hem sidan gör det. Enkelt nog, men låt oss se vad som ligger bakom gardinerna. Här är ett diagram som visar grundflödet för vår ansökan:

Användaren skickar en begäran till vår NodeJs-ansökan. Servern accepterar begäran och skickar den till routern. Efter det vet Render vilken sida som ska användas och returnerar ett svar till servern. I slutet skickas svaret sedan till användaren.

Det finns ytterligare ett element, Data Providers, som förbereder den nödvändiga CSS eller JavaScript för Render (tänk på att i vår exempelapp jag inte använde JavaScript finns det bara en CSS-modul).

Här är vad vår app skulle se ut som en cell, i organisk form:

I cellen har vi ett membran som håller de inre elementen borta från omvärlden. Inne i detta membran är där vi lägger vår första organel, vår Server, för det är här data kan antingen ange eller lämna vår ansökan. De andra organellerna (Router, Render, och CSS) placeras i plasman. Alla dessa moduler kommunicerar med varandra via kemikalier (begäran, sida och css, markerad i rött). Servern avger en begäran kemisk. Routern avger en sida och CSS organel skickar css. Jag bör också nämna att plasmat fungerar som en händelsebuss för kemikalierna. Organelles lyssnar på en viss kemikalie och om de hittas reagerar de på det.

Här är ett annat flödesdiagram, men den här gången med de kemikalier som emitteras (märkt i rött):

Nu om detta koncept fortfarande är oklart för dig, oroa dig inte, eftersom vi fortsätter genom nästa avsnitt och kommer in i själva koden, bör det börja bli mer meningsfullt!


DNA

Allt börjar med DNA (deoxyribonukleinsyra), som du kan tänka dig som en cellkonfiguration. Detta DNA är där du ska definiera dina organeller och deras inställningar.

Låt oss skapa en ny index.js fil och ange följande kod:

var DNA = kräver ("organiskt"). DNA; var Cell = kräver ("organisk"). Cell; var dna = nytt DNA (membran: Server: source: "membrane.Server", plasma: Router: source: "plasma.Router", CSS: source: "plasma.CSS" : "./css/styles.css", Render: source: "plasma.Render", mallar: "./tpl/"); var cell = ny cell (dna);

Ovanstående kod är bara en definition för DNA- och cellinitiering. Du kan se att vi har placerat vår Server i membranet och Routern, CSS och Render i plasma, som vi diskuterade i det sista avsnittet. De källa egendom är faktiskt obligatorisk och innehåller vägen till dina enskilda organeller.

Tänk på att fil egendom i CSS organel och mallar egendom i Render organel är egentligen anpassade egenskaper som jag ställer in. Du kan lägga till vilken anpassning du behöver här också.

Och bara för din referens bör katalogstrukturen för din app se ut så här:

/ css /styles.css / membrane / Server.js / node_modules / plasma / CSS.js /Render.js /Router.js / tpl

En Basic Organel

var Chemical = kräver ("organiskt"). Kemisk; var Organel = kräver ("organiskt"). Organel; var util = kräver ("util"); module.exports = funktion YourOrganelName (plasma, config) Organel.call (detta, plasma); // din anpassade logik här util.inherits (module.exports, Organel);

Ovanstående kod visar det grundläggande formatet för att skapa en organel. Om du vill använda this.emit eller this.on du måste se till att ärva Organel som vi gjorde ovan. Och faktiskt, den plasma parametervariabel har samma exakta metoder (avge och ), så du kan använda plasma direkt och hoppa över arvet om du ville ha det.

Observera också config parameter; Det här är det objekt du definierade i ditt DNA, vilket är ett bra ställe för någon av dina anpassade konfigurationer.


Servern

Servern är din huvudsakliga organel som accepterar förfrågningar och skickar svar till webbläsaren. Så här ser din Serverorganel ut:

var port = 3000; module.exports = funktion Server (plasma, config) Organel.call (detta, plasma); var själv = detta; http.createServer (funktion (req, res) console.log ("request" + req.url); self.emit (new Chemical (typ: "request", req: req), funktion (html) .writeHead (200); res.end (html););). lyssna (port, '127.0.0.1'); console.log ("Server som körs på http://127.0.0.1: '+ port +' / '); 

Två saker händer här. Den första är definitionen av NodeJS-servern, som givetvis har en hanterar accepterande begäran (req) och svar (res) objekt. När begäran har mottagits skickar servernorganet en kemikalie, med typen begäran, anmäler resten av organellerna. Det fäster också req objekt, så den som behöver mer information om den inkommande begäran kan få tillgång till data från kemikalien direkt.

De avge metod tar sedan ett andra argument som är en återuppringningsfunktion. Du kan använda detta för att returnera flödet tillbaka till organeln, som skickar kemikalien. Dvs. När Render avslutar sitt jobb, kallas det serverns återuppringning. Det tar den producerade HTML och med hjälp av res objekt skickar sidan till användaren.


Routern

För vår nästa organel lyssnar routern bara efter a begäran kemikalie, som sänds av servern. Det får URL: en från req objekt och bestämmer vilken sida som ska visas. Här är koden för routern:

module.exports = funktion Router (plasma, config) Organel.call (detta, plasma); var själv = detta; this.on ("request", funktion (kemikalie, avsändare, återuppringning) var page = chemical.req.url.substr (1, chemical.req.url.length); page = page == "" || page = = "/"? "hem": sida; self.emit (new Chemical (typ: "sida", sida: sida, redo: callback);); 

Nu emitterar routern sig bara en ny kemikalie med en typ av sida. Tänk på att det finns två andra organer som lyssnar på den här kemikalien, men som standard överförs den inte till alla andra delar i plasman. Det kan givetvis finnas tillfällen då du behöver en sådan funktionalitet. För att göra det behöver du bara returnera false; i kemikaliens lyssnare. Vi ser detta i åtgärd i nästa avsnitt.


CSS Styles Provider

module.exports = funktion CSS (plasma, config) Organel.call (detta, plasma); var cssStyles = fs.readFileSync (config.file) .toString (); var själv = detta; this.on ("page", funktion (kemisk) self.emit (new Chemical (typ: "css", värde: cssStyles)); return false;); 

Denna modul är bara en enkel en-uppgift organel som får vägen till .css filen, läser den och skickar senare en kemikalie som innehåller de faktiska CSS-stilarna. Också uppmärksamma returnera false; uttalande längst ner. Som jag sa från det sista avsnittet är det viktigt att göra detta, annars kommer inte Render att få det sida kemikalier som skickas av routern. Detta händer eftersom CSS-organeln definieras före Render i DNA.


Renderen

Och till sist, här är koden för vår Render organel:

module.exports = function Render (plasma, config) Organel.call (detta, plasma); var getTemplate = funktion (fil, återuppringning) return fs.readFileSync (config.templates + file);  var formatTemplate = funktion (html, templateVars) för (var namn i templateVars) html = html.replace ("" + name + "", templateVars [name]);  returnera html;  varmallar = layout: getTemplate ("layout.html"). toString (), hem: getTemplate ("home.html"). toString (), om: getTemplate ("about.html"). notFound: getTemplate ("notFound.html"). toString () var vars = ; var själv = detta; this.on ("css", funktion (kemisk) vars.css = chemical.value;); this.on ("page", funktion (kemikalie) console.log ("Opening" + chemical.page + "sida."); var html = mallar [chemical.page]? mallar [chemical.page]: mallar. notFound; html = formatTemplate (templates.layout, innehåll: html); html = formatTemplate (html, vars); chemical.ready (html);); 

Det finns två hjälpar metoder här: getTemplate och formatTemplate som implementerar en enkel mallmotor för att ladda en extern HTML-fil och ersätta mustasch-variabler. Alla mallarna lagras i ett objekt för snabb åtkomst. Efteråt har vi bara några rader för HTML-formatering och sedan är allt klart att gå. Render organel lyssnar också på css kemisk och slutligen ger ansökan en hittades inte 404 sida, om det behövs.

Så här är vad den sista appens katalogstruktur ser ut som:

/ css /styles.css / membrane / Server.js / node_modules / plasma / CSS.js /Render.js /Router.js / tpl /about.html /home.html /layout.html/notFound.html

Kör programmet

Helt enkelt springa nod index.js i konsolen och du bör se något liknande det här:

När din server körs borde du nu kunna besöka http://127.0.0.1:3000 i din favorit webbläsare. Försök att klicka på länkarna för att växla mellan de två sidorna några gånger och sedan gå tillbaka till konsolen för att visa utmatningen.

Du bör se en bra rapport om applikationerna senaste aktiviteten. Nu kan du också märka något annat i konsolen:

Förfrågan /favicon.ico Öppnar favicon.ico sidan.

Du kan se att det finns ytterligare en begäran från webbläsaren. Den vill ladda favicon.ico. Men vår lilla webbplats har inte en sådan ikon, så det öppnar bara 404-sidan. Du kan prova detta själv genom att besöka: http://127.0.0.1:3000/favicon.ico.

Om du vill kolla in hela källkoden för den här handledningen kan du ladda ner den med hjälp av länken till överst på sidan.


Slutsats

Enligt min mening är Organic ett bra koncept. Det är mycket flexibelt och uppmuntrar till att producera bättre applikationer. Tänk på att exemplet i den här artikeln är baserat på min personliga erfarenhet med andra designmönster. Så min användning av termer som Router, Data Provider eller Render är helt frivilligt och du kan ändra namnen som du passar. Gärna experimentera genom att skapa nya moduler baserade på Organic och låt mig veta vad du tycker i kommentarerna!

Kärnan i Organic är utvecklad av Boris Filipov och Valeri Bogdanov och jag rekommenderar starkt att du kolla in dem på Github. Om du är intresserad av att använda organiska, hittar du saker som Angel och WebCell också mycket bra.