基於nodejs的流水線式的CRUD服務。依賴註入可以支持插件。

来源:https://www.cnblogs.com/jyk/archive/2019/04/01/10634950.html
-Advertisement-
Play Games

寫代碼好多年了,發現大家的思路都是寫代碼、寫代碼、寫代碼,還弄了個稱號——碼農。 我是挺無語的,我的思路是——不寫代碼、不寫代碼、不寫代碼! 無聊的代碼為啥要重覆寫呢?甚至一寫寫好幾年。 舉個例子吧,要不然大家肯定很懵。 當我們剛開始學習資料庫編程的時候,我們會先寫一段代碼,實現往一個表裡添加數據的 ...


寫代碼好多年了,發現大家的思路都是寫代碼、寫代碼、寫代碼,還弄了個稱號——碼農。

我是挺無語的,我的思路是——不寫代碼、不寫代碼、不寫代碼!

無聊的代碼為啥要重覆寫呢?甚至一寫寫好幾年。

 

舉個例子吧,要不然大家肯定很懵。

 

當我們剛開始學習資料庫編程的時候,我們會先寫一段代碼,實現往一個表裡添加數據的功能。這段代碼是必須寫的,不寫怎麼會?

然後熟悉這段代碼,儘量知道其含義,越深入越好。

然後呢,進入項目組,發現項目裡面有n張數據表,每個表都至少要有一個添加數據的功能。

那麼怎麼辦?當然要寫代碼了。於是添加數據的代碼被一遍又一遍的寫,區別在於表名和欄位名的不同,因為每個表都有自己的名稱和自己的欄位。

 

僅僅是因為表名和欄位名的不同,就要一遍一遍的寫類似的代碼嗎?這就是我說的無聊的代碼。

 

雖然各位前輩想了很多很多的方法,比如代碼生成器,這樣類似的代碼就不用寫了,直接生成就好。但是當欄位名變了怎麼辦?增加了一個欄位怎麼辦?

 

比如orm,比如各種框架,但是總是要寫代碼。沒發現誰把不寫代碼作為目標。

 

我在這些年裡也在不斷嘗試,雖然有了一些效果,但是缺點還是很多,離不寫代碼還很遠,只是做到了不寫重覆代碼的目的。

 

我一直用c#來實現我的想法,但是c#太嚴謹了,好多思路實現起來太複雜。比如:

1、  必須先定義實體類,然後才能各種傳遞

2、  “插件”實現起來非常不方便。

3、  必須先編譯,然後才能載入。

4、  對json不太友好,需要反覆轉換。

5、  反射、泛型這類的不太理想。

 

 

看了一下其他語言,發現Node非常適合我的想法,也能避免上面的那些“缺點”,只是由於種種原因,現在才開始正式學習。

 

Node使用的是JavaScript,天生對json非常友好,可以直接操作,不用各種轉換。

可以用require載入JavaScript代碼並且立即編譯,可以利用這個特性方便的寫插件。

require也可以載入json文件,這樣依賴註入就很容易實現了。

 

性能方面也不用擔心,畢竟阿裡爸爸都在用。

  

好吧,介紹一下思路,上流程圖

 

 

這是初步想法,具體細節還在不斷完善。

 

下麵是第一版代碼,很初級,只是實現基本功能,因為這是我第一次寫node,邊熟悉node的寫法和基本功能,邊實現我的想法。

 話說,語言裡面沒有node呢,只好選擇JavaScript了。

/**
 * Created by jyk00 on 2019/3/31.
 * 添加數據的服務
 */


exports.start = function(code) {
    console.log('開始添加數據');

    /** 根據配置信息實現添加數據的功能
     * 獲取服務信息
     * 接收數據
     * 驗證數據
     * 調用插件
     * 持久化
     * 獲取持久化後數據
     * 寫數據變化日誌
     * 返回結果
    */

    //獲取服務信息
    console.log('服務ID:' + code);
    var meta = require('./serviceAdd_'+ code +'.json');
    console.log('獲取服務信息:' + meta);

    //獲取實體類,先模擬一下
    var data = require('./node_user.json');

    //驗證數據,暫時略

    //調用持久化前的插件

    //持久化
    saveData(function(err, result) {
        console.log('#######################');
        console.log('saveData的回調');
        console.log('result:', result);

    });

    //調用持久化之後的插件

    //記錄數據變化日誌

    //持久化數據
    function saveData(callback) {
        console.log('開始持久化');
        //創建mysql對象
        var mysql  = require('mysql');
        var cnString = require('../sqlConnection.json');
        var connection = mysql.createConnection(cnString);

        var sql = meta.sqlCache;
        //拼接數據
        var valuesParams = createParams();

        connection.connect();
        connection.query(sql,valuesParams,function (err, result) {
            if(err){
                console.log('[INSERT ERROR ] - ',err.message);
                callback(err, result);
                return;
            }
            console.log('-------INSERT by service ----------');
            console.log('INSERT ID:',result.insertId);
            console.log('#######################');

            callback(err, result);

        });

        connection.end();
        console.log('調用結束等待結果');

    }

    //拼接valuesParams
    function createParams(){
        console.log('開始拼接數據數組');

        var params = [];
        //數據變成數組的形式
        var colName = "";
        for (var i=0 ;i<meta.column.length;i++) {
            colName = meta.column[i];
            params.push(data[colName]);
        }

        return params;

    }
 

};

  

 

下麵是第二版代碼,功能多了一些,代碼也更難看了,都是非同步害的。這麼醜陋的代碼,肯定要進行改善的。

/**
 * Created by jyk00 on 2019/3/31.
 * 添加數據的服務
 */


exports.start = function(code) {
    console.log('開始添加數據');

    /** 根據配置信息實現添加數據的功能
     * 獲取服務信息
     * 接收數據
     * 驗證數據
     * 調用插件
     * 持久化
     * 獲取持久化後數據
     * 寫數據變化日誌
     * 返回結果
    */

    //獲取服務信息
    console.log('服務ID:' + code);
    var meta = require('./serviceAdd_'+ code +'.json');
    console.log('獲取服務信息:' + meta);

    //獲取實體類,先模擬一下
    var data = require('./node_user.json');

    //驗證數據,暫時略

    //調用持久化前的插件
    var plugName = meta.pluginBefore;
    if (plugName.length === 0){
        //沒有插件,不調用
        console.log('沒有插件,不調用');
        //持久化及後續
        saveAndLast(data);
    }
    else
    {
        //有插件
        console.log('有插件,調用');
        var plug = require('../plugin/' + plugName);
        plug.begin(data,function(data){
            //持久化及後續
            saveAndLast(data);
        });

    }

    //持久化以及之後的事情
    function saveAndLast(data) {
        //持久化
        saveData(data,function(err, result){
            console.log('#######################');
            console.log('saveData的回調:' + data.age);
            console.log('result:',result);

            //調用持久化之後的插件
            plugName = meta.pluginAfter;
            if (plugName.length === 0){
                //沒有插件,不調用

                //記錄數據變化日誌
            }
            else{
                //有插件
                plug = require('../plugin/' + plugName);
                plug.begin(err, result,data,function() {

                    //記錄數據變化日誌
                });
            }

        });


    }

    //持久化數據
    function saveData(data,callback) {
        console.log('開始持久化');
        console.log('saveData的age:' + data.age);
        //創建mysql對象
        var mysql  = require('mysql');
        var cnString = require('../sqlConnection.json');
        var connection = mysql.createConnection(cnString);

        var sql = meta.sqlCache;
        console.log('sql:' + sql);
        //拼接數據
        var valuesParams = createParams(data);

        connection.connect();
        connection.query(sql,valuesParams,function (err, result) {
            if(err){
                console.log('[INSERT ERROR ] - ',err.message);
                callback(err, result);
                return;
            }
            console.log('-------INSERT by service ----------');
            console.log('INSERT ID:',result.insertId);
            console.log('#######################');

            callback(err, result);

        });

        connection.end();
        console.log('調用結束等待結果');

    }

    //拼接valuesParams
    function createParams(data){
        console.log('開始拼接數據數組');
        console.log('createParams的age:' + data.name);
        var valuesParams = [];
        //數據變成數組的形式
        var colName = "";
        for (var i=0 ;i<meta.column.length;i++) {
            colName = meta.column[i];
            valuesParams.push(data[colName]);
        }

        return valuesParams;

    }
 

};

  

今天先到這裡,代碼在不斷改進中。以上代碼都是可以正常運行的。

第二版的代碼,有很多缺點,比如層次不分明,思路混亂,沒法擴展。因為這還只是單表的添加,那麼主從表的添加呢,批量添加又怎麼辦?還是要不斷的改進的。 

 


您的分享是我們最大的動力!

-Advertisement-
Play Games
更多相關文章
  • 資料庫什麼是資料庫就是存儲數據的倉庫(容器)存儲數據的方式1.變數 無法永久存儲2.文件處理 ,可以永久存儲文件處理存在的弊端: 1.文件處理速度慢 2.文件只能在自己的電腦上讀寫 無法被共用(區域網除外)單台電腦的性能終歸是有限的1.升級你的硬體設備 提升幅度有限 垂直擴展2.伺服器集群 分佈 ...
  • 在筆記本和PC上面使用Mysql8.0.11免安裝版本,均遇到此問題,記性不太好,現做下筆記。 1.cmd下,先關掉已啟動的mysql服務,使用命令:net stop mysql 2.步驟1的cmd視窗a不關閉,重新開1個cmd視窗b,輸入:mysqld --console --skip-grant ...
  • 資料庫的基本操作 1. 創建資料庫 database_name為要創建的資料庫的名稱 2. 刪除資料庫 database_name為要刪除的資料庫的名稱 3. 資料庫存儲引擎 資料庫存儲引擎是資料庫底層軟體組成,資料庫管理系統(DBMS)使用數據引擎進行創建、查詢、更新和刪除數據操作。 MySQL的 ...
  • [20190401]那個更快的疑問.txt--//前一陣子,做了11g於10g下,單表單條記錄唯一索引掃描的測試,摘要如下:--//參考鏈接:http://blog.itpub.net/267265/viewspace-2636321/http://blog.itpub.net/267265/vie ...
  • 下圖展示了 LEFT JOIN、RIGHT JOIN、INNER JOIN、OUTER JOIN 相關的 7 種用法。 具體分解如下: 1、INNER JOIN(內連接) 2、LEFT JOIN(左連接) 3、RIGHT JOIN(右連接) 4、OUTER JOIN(外連接) 5、LEFT JOIN ...
  • 1.我們使用緩存時的業務流程大概為: 當我們查詢一條數據時,先去查詢緩存,如果緩存有就直接返回,如果沒有就去查詢資料庫,然後返回。這種情況下就可能出現下麵的一些現象。 2.緩存穿透 2.1什麼是緩存穿透 緩存穿透是指查詢一個一定不存在的數據,由於緩存是不命中時被動寫的,並且出於容錯考慮,如果從存儲層 ...
  • 最近做ogg數據同步,然後觸發器加工數據放入另外一張表,由於數據量很大,一分鐘幾萬條數據,由於一些條件欄位類型不匹配,引起ogg阻塞,比較頭大。最後分析發現性能問題。請看下圖: phmxxh是varchar2類型,note_id是integer類型,用to_char轉換以後,性能提高60倍以後註意避 ...
  • 筆記記錄自林曉斌(丁奇)老師的《MySQL實戰45講》 (本篇內圖片均來自丁奇老師的講解,如有侵權,請聯繫我刪除) 14) --count(*)這麼慢,我該怎麼辦? 有時你會發現,隨著系統中記錄數越來越多,select count(*) from t執行得也越來越慢。那麼今天,我們就來聊聊count ...
一周排行
    -Advertisement-
    Play Games
  • 移動開發(一):使用.NET MAUI開發第一個安卓APP 對於工作多年的C#程式員來說,近來想嘗試開發一款安卓APP,考慮了很久最終選擇使用.NET MAUI這個微軟官方的框架來嘗試體驗開發安卓APP,畢竟是使用Visual Studio開發工具,使用起來也比較的順手,結合微軟官方的教程進行了安卓 ...
  • 前言 QuestPDF 是一個開源 .NET 庫,用於生成 PDF 文檔。使用了C# Fluent API方式可簡化開發、減少錯誤並提高工作效率。利用它可以輕鬆生成 PDF 報告、發票、導出文件等。 項目介紹 QuestPDF 是一個革命性的開源 .NET 庫,它徹底改變了我們生成 PDF 文檔的方 ...
  • 項目地址 項目後端地址: https://github.com/ZyPLJ/ZYTteeHole 項目前端頁面地址: ZyPLJ/TreeHoleVue (github.com) https://github.com/ZyPLJ/TreeHoleVue 目前項目測試訪問地址: http://tree ...
  • 話不多說,直接開乾 一.下載 1.官方鏈接下載: https://www.microsoft.com/zh-cn/sql-server/sql-server-downloads 2.在下載目錄中找到下麵這個小的安裝包 SQL2022-SSEI-Dev.exe,運行開始下載SQL server; 二. ...
  • 前言 隨著物聯網(IoT)技術的迅猛發展,MQTT(消息隊列遙測傳輸)協議憑藉其輕量級和高效性,已成為眾多物聯網應用的首選通信標準。 MQTTnet 作為一個高性能的 .NET 開源庫,為 .NET 平臺上的 MQTT 客戶端與伺服器開發提供了強大的支持。 本文將全面介紹 MQTTnet 的核心功能 ...
  • Serilog支持多種接收器用於日誌存儲,增強器用於添加屬性,LogContext管理動態屬性,支持多種輸出格式包括純文本、JSON及ExpressionTemplate。還提供了自定義格式化選項,適用於不同需求。 ...
  • 目錄簡介獲取 HTML 文檔解析 HTML 文檔測試參考文章 簡介 動態內容網站使用 JavaScript 腳本動態檢索和渲染數據,爬取信息時需要模擬瀏覽器行為,否則獲取到的源碼基本是空的。 本文使用的爬取步驟如下: 使用 Selenium 獲取渲染後的 HTML 文檔 使用 HtmlAgility ...
  • 1.前言 什麼是熱更新 游戲或者軟體更新時,無需重新下載客戶端進行安裝,而是在應用程式啟動的情況下,在內部進行資源或者代碼更新 Unity目前常用熱更新解決方案 HybridCLR,Xlua,ILRuntime等 Unity目前常用資源管理解決方案 AssetBundles,Addressable, ...
  • 本文章主要是在C# ASP.NET Core Web API框架實現向手機發送驗證碼簡訊功能。這裡我選擇是一個互億無線簡訊驗證碼平臺,其實像阿裡雲,騰訊雲上面也可以。 首先我們先去 互億無線 https://www.ihuyi.com/api/sms.html 去註冊一個賬號 註冊完成賬號後,它會送 ...
  • 通過以下方式可以高效,並保證數據同步的可靠性 1.API設計 使用RESTful設計,確保API端點明確,並使用適當的HTTP方法(如POST用於創建,PUT用於更新)。 設計清晰的請求和響應模型,以確保客戶端能夠理解預期格式。 2.數據驗證 在伺服器端進行嚴格的數據驗證,確保接收到的數據符合預期格 ...