CoreCRM 開發實錄——開始之新項目的技術選擇

来源:http://www.cnblogs.com/holmescn/archive/2016/12/29/corecrm-startup.html
-Advertisement-
Play Games

2016年11月,接受了一個工作,是對“悟空CRM”進行一些修補。這是一個不錯的 CRM,開源,並提供一個 SaaS 的服務。正好微軟的 .NET Core 和 ASP.NET Core 也發佈了。於是就有了這個想法:使用 ASP.NET Core 來開發一個 CRM。當然這裡面的私心是:朝後坦白講 ...


2016年11月,接受了一個工作,是對“悟空CRM”進行一些修補。這是一個不錯的 CRM,開源,並提供一個 SaaS 的服務。正好微軟的 .NET Core 和 ASP.NET Core 也發佈了。於是就有了這個想法:使用 ASP.NET Core 來開發一個 CRM。當然這裡面的私心是:朝後坦白講,悟空CRM 的代碼真的是不怎麼樣。大量的代碼堆在 Controller 里,多個功能在一個 EndPoint 里混合。許可權管理也有些亂來。View 里充滿了“臨時解決方案”。所以我真的是一邊改,一邊難受。由於11月我還在做一個 Xarmin 的小程式,所以對 CoreCRM 的開發就定在12月開始了。

因為修改悟空CRM,本來以為對業務的邏輯已經比較熟悉,先開始的時候照著悟空CRM的UI直接開始擼就可以了。在嘗試了幾個頁面之後發現這樣比自己直接寫還麻煩。而在這中間,我的老毛病有犯了:在幾種技術方案之間不停地權衡和嘗試。這樣,時間就一天天的浪費掉了。技術方案的選擇經歷了:VueJS + jQuery,React.NET,aspnetcore-spa (ReactJS + Redux),最後又回到 VueJS + jQuery。CSS 框架使用的是 Bootstrap 3.3.6,這個是一直沒有變(雖然我也曾經想過使用4.0的alpha版,不過最後還是忍住了)。圖標使用了font-awesome 4.7.0,也是沒有改。一直折騰了一個月(這中間還有因為對 ASP.NET Core 不夠熟悉而付出的學習成本),整個12月將要過完的時候,我才只完成了 Layout 和 Login。(其實原來的首頁、結構架構也完成了,但只有UI的部分)。

關於技術選擇

為什麼要選擇 ASP.NET Core?

我的一個基本判斷是:帶有類型檢查的語言應該是未來的趨勢。雖然從歷史角度看,動態類型和靜態類型總是交替上臺表演的。不過,隨著程度規模的不斷變大(想當年一個 DOS 程式就幾十,幾百K,求伯君可以使用彙編擼一個 WPS 出來,而現在一個手機 App 也是幾十MB),動態語言的一些不方便的方面是突顯出來了。特別是多人協作開發的時候,因為沒有類型的靜態類型檢查,很多錯誤都只能在運行的時候才能發現。其實這個問題如果配合上足夠的單元測試,也是可以減輕一些的,然而到了2016年,還是有很多人把測試當成負擔。結果就是大量的 bug 和安全漏洞,以及改了補了一個洞,又開了三個洞。

從現實情況看,PHP 7 已經引入了一些類型標註,Python 3.5 也有這樣的東西,JS 系裡有 TypeScript 這樣的 Transpiler(而且,Angular 2 這樣的框架已經開始在使用 TypeScript 進行開發了),以及 Facebook 的 flow。所以,動態語言在漫漫的靜態化。雖然只是提供了類型的運行前檢查,但也減少了很多運行時的問題。

那麼,現在比較成熟的靜態類型語言,我知道的就是三個:C++、Java 和 C#。C++ 是出了名的複雜和開發效率低下。雖然我對 C++ 的熟悉程度比 C# 要高的多,但 C++ 做 Web 的挑戰還真是大得讓我不敢嘗試。Java 雖然現在是 TOIBE 上排前三的語言,也一度占到了榜首好多年,但我還是不太喜歡 Java。我覺得 Java 寫進來太死板,太多的架構代碼,感覺很瑣碎。最後我選了 C# 這個 sugar language。然而,其實我也不太會 C#,今年並沒有安排學習 C# 的任務。只是年初的時候因為學習 F#,所以學了一點點的 C#。但用起來還真的不錯。同時,微軟終於開眼,開始與開源社區深入合作,而不是把開源當成敵人,於是有了 .NET Core 這個跨平臺的 Runtime。

遇到一個問題

中間的一次挫折,差點讓項目中斷。ASP.NET Core 的 ORM 使用的是 Entity Framework Core,而 EF Core 基本上是對固定的模型比較好用。而 CRM 這種需要定製的系統,需要對一些表進行定製(比如一個客戶需要保存哪些信息,這不可能有一個通過的模板)。我嘗試了幾種可能的方案,都不能在 EF Core里實現動態的模型。本來以為自己又一次做錯了架構選擇,不過,退後一步想,我為什麼非要使用 EF Core呢?然後去搜了一下,發現 StackOverflow 的 Dapper.NET 可以支持動態的 model。於是這個危機才算解除。

前端框架選哪個?

因為後端的技術選擇了 ASP.NET Core,這就對前端的技術選擇造成了一定的限制。如果我是使用 PHP 或者 Python 開發的話,我可能會使用前後端分離的技術。但 ASP.NET Core 對 HTML 這個層做了一些的工作(我想JSP可能也是這樣的),比如根據運行時的環境選擇載入不同的 JS 和 CSS 文件(還支持 CDN 的 fallback,非常貼心);支持 class 的自動補全和智能提示(這個非常提升生產力),甚至還支持對 Font-awesome 的預覽;支持 Partial View 和 View Component,也就是對 View 的按功能分割也可以直接實現。所以,前端的部分其實只是做一些局部的更新。

現實局部更新最簡單粗暴的方法就是使用 jQuery。不過,jQuery 的時代已經過去了,那種 query and modify 的時代已經和現在這個 MVVM 一統天下的局面不符合了。使用 jQuery,必然還需要在 JS 里寫一些難看的 HTML。所有的結果就是導致代碼的維護成本高起。而在 2016 年,我們有什麼樣的前端框架可以選擇呢?首先是我最喜歡使用的 VueJS,這個其實算不得一個 framework,最多是一個 micro-framework,提供了 view model 和 model 的綁定和雙向更新;一些條件渲染和組件化。使用進來非常簡單和直接。可我為什麼還要配合上 jQuery 呢?主要是因為要使用 bootstrap 的一個 JS 組件。但在直接使用 VueJS + jQuery 這個方案的時候,還是有一些問題。因為我沒有做伺服器端渲染(SSR),所以頁面在打開的時候總會閃一下,那個是 VueJS 對模板重新編譯再插入到 DOM 造成的。好像 VueJS 1.x 的時候沒有這個問題,2.x 引入了 virtual DOM,好像也引入了這個問題。解決方法比較直接的就是SSR,不過,我準備使用非同步組件的方式來做。

ReactJS一直是我想嘗試的一個前端框架。因為不但可以在 Web 里使用,還可以把同樣的經驗轉移到 React Native 的開發中。比如 Route、Rudex 等都是相通的。同時 React 也直接實現了 SSR,解決了前面說的問題。為了嘗試 ReactJS,我前後嘗試了兩個技術:ReactJS.NET 和 aspnetcore-spa。前者是 Facebook 出品,後者是微軟出品。ReactJS.NET的優勢是:有一些 Tag Helper,可以和 ASP.NET Core 的 View 整合的比較好。但遇到的一個問題是,在 macOS 上沒法運行。雖然我已經提了 issue,和一個 pull-request,但問題好像不會在短時間內解決。只好先放棄這的方案。

微軟自己搞的 aspnetcore-spa,只可以在各種平臺運行的。但使用的時候發現:1. className 沒有 class 的補全功能;2. Server-Side 的驗證還沒法整合(雖然在 README 里寫了這條,但沒有 docs,不知道怎麼用)。

也就是說,ReactJS 的兩種方案,就算可以使用,也因為破壞了 ASP.NET Core 的 View 直接提供的功能而在使用的時候不免遇到各種問題。而嘗試這兩種方案,消耗了我兩周的時間(要研究怎麼用,發現問題,解決問題,與社區溝通……)

最後,還是回到了 VueJS + jQuery 的道路上來了。不過,使用方法做了一些改變。最初的使用方法是:在 body 下麵創建一個 div 做為所以內容的 container,然後把各種 modal, list 都扔進去,掛上 attribute。這樣的結果就是:因為有好多的 modal,和一些 list,結果整個模板變得很大,編譯的時候就會閃。新的方法是,使用 Vue 的動態組件的功能,在需要載入的時候,通過一個獨立的 Controller 載入到頁面,雖然在載入的時候會顯示一個 Loading,但因為每個組件都不大,應該不是什麼大問題。

公開的開發過程

CoreCRM 選擇使用 Apache 2.0 協議開源(其實我也不知道應該選什麼,MIT、BSD 好像都不錯的樣子)。反正代碼都開源了,開發的過程我也開放出來好了。這裡我會記錄每一次開發的思考、決策和反思。

如前所述,目前 CoreCRM 還在初級階段,只有登錄和登錄的做成測試。不過,在這篇文章這後,項目會慢慢展開。

持續集成

在12月初的開發中,我並沒有引入持續做成。一開始的三天是在混沌中度過的。然後我決定先寫 UI(HTML和CSS),然後再把後端完成,最後前後端集成。實踐的結果是:因為一直在寫UI,所以感覺一直沒有什麼進展,除了登錄,什麼功能也不能使用。這樣的感覺很不好。特別是只有我一個人在開發的時候,更需要一些小的成功來激勵我繼續前進。所以,在 12 月的第四周,我開始研究怎麼使用持續集成(因為離發佈還很遠,所以,所有的發佈功能都被關閉了)。現在已經接入了 Travis-CI 和 AppVeyor 兩個 CI 平臺。登錄功能的測試也已經通過。

代碼庫和項目管理

這裡有一個問題:因為我是使用 Coding.NET 做為主要的版本庫的(因為這個服務是在國內,速度上比 GitHub 要快一些),但 Travis 並不支持非 GitHub 的 Git Repo,所以,只好再在 GitHub 上開一個鏡像。雖然 AppVeyor 可以直接使用 Coding.NET,我也沒配置這個功能(只是嘗試了一下,然後刪的時候刪錯了……)現在兩個 CI 都配置在 GitHub 上了(那你幹嘛不直接就在 GitHub 上搞?)。反正現在只有我一個人搞,這還不是一個問題。如果以後有其他人一下參與,我可以做一下同步的功能,自動把 Coding.NET 的代碼同步到 GitHub 上進行測試。

使用 Coding.NET 的一個原因是,Coding.NET上還支持一些簡單的項目管理。這樣,可以直接在上面寫任務,完成任務,也是一種項目開發的體驗。如果以後有多人參與了,在持續集成方面,我還想把 Worktile 拉進來(測試完成後的提示等)。

邀請

如果你也對 ASP.NET Core 和 .NET Core 的未來感興趣,想參與到這個項目中來,歡迎到 Coding.NET 上關註這個項目。在這裡你將能學到:

  1. ASP.NET Core
  2. VueJS
  3. 單元測試
  4. 集成測試
  5. More

項目地址:

https://coding.net/u/holmescn/p/CoreCRM/git

https://github.com/holmescn/CoreCRM


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

-Advertisement-
Play Games
更多相關文章
  • 這個問題是由於在cshtml中 引用了model這個單詞 它可能和Model在解析時有衝突。 解決方法:把model換成別的單詞就可以了。 ...
  • ●節點分為不同的類型:元素節點、屬性節點和文本節點等。 ●getElementById()方法將返回一個對象,該對象對應著文檔里的一個特定的元素節點。 ●getElementsByTagName()方法將返回一個對象數組,它們分別對應著文檔里的一個特定的元素節點。 ●這些節點中的每個都是一個對象。接 ...
  • 在使用開源項目 SENPARC.WEIXIN SDK 調用微信支付介面的時候出現了WeixinPayInfoCollection尚未註冊Mch,這個問題。 最後地解決方案是: 我這個傻逼忘了在全局Global初始化TenPayV3InfoCollection 只要在Global 添加以下代碼 //提 ...
  • 實例生命周期決定在同一個服務的每個請求的實例是如何共用的。 當請求一個服務的時候,Autofac會返回一個單例 (single instance作用域), 一個新的對象 (per lifetime作用域) 或者在某種上下文環境中的單例。比如 一個線程 或者一個HTTP請求 (per lifetime ...
  • 學習uwp開發也有一段時間了,最近上架了一個小應用(China Daily),現在準備將開發中所學到的一些東西拿出來跟大家分享交流一下。 先給出應用的下載鏈接:China Daily , 感興趣的童鞋可以看一看。 廢話就扯到這裡,接下來,我們來看看這個應用中的劃詞翻譯功能是如何實現的(也順帶談談點擊 ...
  • 只要是軟體,它就有可能存在一些問題,即使它看起來能正常的工作。 造成軟體異常的原因很多,如用戶的非法輸入,程式演算法錯誤造成的記憶體溢出,通信網路故障,程式的配置文件被破壞、刪除... .Net的異常處理 .Net平臺提供了一種標準技術(結構化異常處理[SEH])來發和捕獲運行時錯誤;結構化異常處理的優 ...
  • 方法註入, 其實就是在註冊類的時候, 把這個方法也註冊進去. 那麼在生成實例的時候, 會自動調用這個方法. 其實現的方法, 有兩種. 準備工作: 1. 方法一 - 常規方法 執行時機 : 首先執行的, 肯定是Person的構造函數, 然後回去調用這個方法, 調用過程中, 發現了IAnimal 參數, ...
  • 在園子也逛了快5年了,一直在學習別人的經驗,在工作中也是發現問題,網上找解決方案,然後照葫蘆畫瓢,每次都想著要留下點什麼,可總是以各種理由忘記寫。今天終於鼓起勇氣開通了博客,希望以後能把每次遇到問題的解決方案留下給後來者。同時把一些經驗分享給大家。 ...
一周排行
    -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.數據驗證 在伺服器端進行嚴格的數據驗證,確保接收到的數據符合預期格 ...