2020年10月30日 星期五

重新踏入網頁開發 (4) - Dependency injection

耦合性 (Coupling,dependency)

    耦合性是指一程式中,模組及模組之間資訊或參數依賴的程度。低耦合性是結構良好程式的特性,低耦合性程式的可讀性及可維護性會比較好。舉例來說 Module A 使用了 Module B 功能, 今天 Module B 更改了功能而造成 Module A 必須也更改使用其功能的邏輯, 則會說 Module A 對 Module B 依賴程度高, 具有高耦合性。所以你要維護 B 就要一起維護 A, 邏輯參在一起想必 module 的可重複使用率也低。

解耦 > Dependency injection

    高耦合 > 解耦 > 低耦合。解耦方法很多這裡使用的是 Dependency injection (依賴注入>///<)。拿前幾些章節裡的 Server 跟 Route 舉例。
    沒有依賴注入的 Server + Route
  • route.js
        export function regular_route(pathname) {
            console.log("Start routing path name \"" + pathname + "\"");
        }
  • Server.js
        import http from 'http'
        import url from 'url'
        import { regular_route } from './route.js';
    
        export function serverStart() {
            function onRequest(request, response) {
                var path_name = url.parse(request.url).pathname;
                console.log("Request for " + path_name + " received");
                
                // my Route function
                regular_route(path_name);
    
                response.writeHead(200, {"Content-Type": "text/plain"});
                response.write("Hello World.\n");
                response.end();
            }
            http.createServer(onRequest).listen(8888);
            console.log("Server has started...");
        }
  • index.js
        import {serverStart} from './Server.js'
        serverStart();
    老實說看起來像最佳解, 但當你要換另一種 routing function, 你正常來說要更改 2 個地方。import 的部份可能要改, 因為是新的檔案或其他大 module 裡的 route function。function name 可能要改, 因為新的 routing function 不叫 regular_route。驗證了上面所說的你改 B 結果 A 也要跟著改,量子糾纏...阿不對是"高耦合"。才 2 個看起來還好,但隨著專案擴的越大,你改 routing function 的時間成本也越大,甚至改天不用 route 用其它東西去處理 URL,那就更慘了。
    依賴注入的 Server + Route
    這邊切入的點是 Server 這 module 主要不變工作應該只有接收與回覆,中間的 routing function 是會依照時空背景不同去更動(沒錯,就是這麼彈性且有價值,誰說整天看政治新聞沒用的),可以被抽象化成一個動作,而這個動作可以當作參數傳進 Server 這 module。(說穿了就是做 callback function)
  • route.js (沒變)
        export function regular_route(pathname) {
            console.log("Start routing path name \"" + pathname + "\"");
        }
  • Server.js
        import http from 'http'
        import url from 'url'
    
        export function serverStart(route) {
            function onRequest(request, response) {
                var path_name = url.parse(request.url).pathname;
                console.log("Request for " + path_name + " received");
                
                // my Route function
                route(path_name);
    
                response.writeHead(200, {"Content-Type": "text/plain"});
                response.write("Hello World.\n");
                response.end();
            }
            http.createServer(onRequest).listen(8888);
            console.log("Server has started...");
        }
  • index.js
        import { serverStart } from './Server.js'
        import { regular_route } from './route.js';
        serverStart(regular_route);
    這樣你改 routing function 就不會需要動到 Server.js (改成動index.js...),甚至改傳吃豬肉這 function,Server 也照執行沒什麼問題。
上一篇 :
下一篇 :
參考資料 :

2020年10月29日 星期四

重新踏入網頁開發 (3) - Route

Route ( URL )

    通過不同的 URL 去區別不同請求
  • Server.js
        import http from 'http'
        import url from 'url'
    
        function onRequest(request, response) {
            // 會紀錄 request url
            var path_name = url.parse(request.url).pathname;
            console.log("Request for " + path_name + " received");
            response.writeHead(200, {"Content-Type": "text/plain"});
            response.write("Hello World.\n");
            response.end();
        }
    
        http.createServer(onRequest).listen(8888);
        console.log("Server has started...");
  • 用 curl 去 request
        $ curl http://localhost:8888/
        Hello World.
        $ curl http://localhost:8888/students/1
        Hello World.
  • 伺服器端顯示
        $ node Server.js 
        Server has started...
        Request for / received
        Request for /students/1 received
上一篇 :
下一篇 :
參考資料 :

2020年10月28日 星期三

Node.js - 支援 ES6 module

Nodejs 支援 ES6 module

    要讓 nodejs 去支援 ES6 module,必須去改寫 package.json。
    開啟一個新的 nodejs project
  • 首先是 node package manager
        npm init
        # 應該會有一堆要填的,若沒任何想法可以改下 npm init -y 自動幫你填完
  • 這時候多一個 package.json 的檔案,裡面有你剛填的資料
        {
          "name": "react",
          "version": "1.0.0",
          "description": "",
          "main": "index.js",
          "scripts": {
            "test": "echo \"Error: no test specified\" && exit 1"
          },
          "repository": {
            "type": "git",
            "url": "git+https://github.com/JunYe1993/React.git"
          },
          "author": "JunYe1993",
          "license": "ISC",
          "bugs": {
            "url": "https://github.com/JunYe1993/React/issues"
          },
          "homepage": "https://github.com/JunYe1993/React#readme"
        }
  • package.json 裡多加一個設定
        ...
          "type": "module"
        }
    若 node 版本低於 v13, 會噴 Warning。
  • node 版本低於 v13
        $ node HelloWorld.js 
        (node:29009) ExperimentalWarning: The ESM module loader is 
        experimental.
        Hello World
參考資料 :

2020年10月27日 星期二

重新踏入網頁開發 (2) - ES6

模組化

    Ryan Dahl 創造的 node.js 專案之所以如此重要, 是因為其理念為 模組(module), 讓 javascript 的大規模專案得以實現, 也讓 javascript 可以做伺服器端程式設計。

node.js 的模組

    這裡示範 node.js 原生的模組,
  • moduleA.js
        // 想像這裡有隱藏程式碼
        // # var module = new Module(...);
        // # var exports = module.exports;
        // index.js 在 call "require("./ModuleA");"
        // 等於回傳 module.exports
        var name = "JunYe";
        exports.name = name;
  • moduleB.js
        // 想像這裡有隱藏程式碼
        // # var module = new Module(...);
        // # var exports = module.exports;
        // index.js 在 call "require("./ModuleB");"
        // 等於回傳 module.exports
        var name = "Daniel";
        exports.name = name;
  • index.js
        var a = require("./moduleA");
        var b = require("./moduleB");
        console.log(a.name + " and " + b.name + " both are the best.");
  • 執行 node index.js
        $>:node index.js 
        JunYe and Daniel both are the best.

ES6 的模組

    ES6 是較新的 javascript 規範, 沒錯就是規範, javascript 並非正規的程式語言, 而是一種語言規範, 而其 runtime 的執行則讓各個瀏覽器引擎決定(nodejs也是其中之一)。雖然 ES6 是較新的規範, 但大部分的瀏覽器都有支援了。以下為 nodejs 支援 ES6 的示範
  • studentA.js
        export var _name = "JunYe";
        export var _class = "SSS";
        export var _number = "3064";
  • function.js
        export function intro (name, number) {
            console.log("My name is " + name + ", and my number is " + number);
        };
  • index.js
        // 要在 package.json 加 type: module
        // 才能達到 <script src="./function.js" type="module"></script> 的效果
        // 這邊不知道為什麼要加 .js 才給過
        import { intro } from "./function.js";
        import { _name, _number } from "./studentA.js";
        intro(_name, _number);
  • 執行 node index.js
        $>:node index.js 
        My name is JunYe, and my number is 3064
上一篇 :
下一篇 :
參考資料 :

2020年10月10日 星期六

重新踏入網頁開發 (1) - Nodejs

前言

    網頁開發是一個對我而言還蠻陌生的東西, 因為我都是自學所以總是得過且過。自學通常就會拿手邊資源也就是公司內部系統的 Code。公司的 Code 較為古早, 不外乎 3 個基本的元素, http server(apache), PHP, 前端(html, css, javascript)。 此時的我靠著 w3schools 就能完成所有事情。既然重新踏入開發網頁, 就去學最新的東西 (目標是 react), 即使路途遙遠, 但相對的有很多東西可以紀錄。

Node.js

    離開了較為古老的開發方法後, 進入到所謂較為現代網站開發, 查了查似乎都繞不開 node.js。所以我想在這個下點功夫, 學學這個可以在後端執行的 javascript。

    學程式學語言的第一步通常是 Hello World,所以那就來吧。(當然要先裝 Node.js)
  • 創一個檔案 HelloWorld.js
        console.log("Hello World");
  • 在 CMD 執行 HelloWorld.js
        $>node HelloWorld.js
        Hello World
    再一個貨真價實的後端 Hello World
  • 創一個檔案 Server.js
        var http = require("http");
    
        http.createServer(function (request, response) {
            response.writeHead(200, { "Content-Type": "text/plain" });
            response.write("Hello World");
            response.end();
        }).listen(8888);
  • 在 CMD 執行 Server.js (如果你是 windows 請按允許存取)
        $>node Server.js
    
    
  • 開啟瀏覽器, 讀取 http://localhost:8888/ (chrome 書籤太多...科)

結語

    老實說上面的程式碼對我來說還蠻震驚的, 因為它取代了 apache (http server), 一個我從來懶得去研究的東西。看來路途比想像的遙遠
下一篇 :
參考資料 :

Popular Posts