解析大型.NET ERP系統架構設計 Framework+ Application 設計模式

我對大型系統的理解,從數量上面來說,源代碼超過百萬行以上,系統有超過300個以上的功能,從質量上來說系統應該具有良好的可擴展性和可維護性,系統中的功能緊密關聯。除去業務上的複雜性,如何設計這樣的一個協做良好的系統,搭建開發人員基礎平臺,一直是我研究的方向。html

SouceCounter(版本3.3.91.79)對源代碼的統計信息以下:程序員

image

下面來詳細解析一下這個系統的設計架構,純.NET技術架構方案,C/S WinForms系統。數據庫

系統分爲Framework和Application兩個部分,前者是框架(Framework),包含核心的基礎功能,如公共類庫,許可受權,數據字典,公共控件,公共窗體,多線程組件,通訊基礎,會話管理等基礎部分,後者是應用部分,根據業務邏輯的不一樣,對於ERP系統而言,可分爲進銷存(Distribution),工程(Engineering),生產(Production),生產計劃(Production Planning),財務(Account Receivable,Account Payable,General Ledger),客戶關係(CRM)等模塊。瀏覽器

 

Framework 開發框架

1.  Common 公共類庫

  • 定義異常類型,用於系統異常處理:LicenseException 許可受權異常,字段驗證異常FieldValidationException,實體驗證異常,應用程序異常AppException,水晶報表異常CrystalReportException。
  • 定義版本信息,設定四個版本字段的值
public const string Major = "3";
public const string Minor = "4";
public const string Build = "0";
public const string Revision = "0";
  • 定義許可受權方案, SystemLicense系統許可文件,HaredwareInformation硬件信息。SystemLicense中包含一個核心的方法Verify,用於驗證受權許可,好比過時時間,版本(Standard標準版,企業版Enterprise),硬件信息,參數設置(最大用戶數,可用模塊數量,可用數據庫)。
public enum LicenseType
{
       Internal,
       Standard,
       Enterprise
}
  • 優化.NET DataSet傳輸,主要是AdoNetHelper,這個類型來自CodeProject上的一篇文章,標題是Optimize .NET DataSet,徹底自定義DataSet在.NET Remoting服務器和客戶端傳輸方法。
  • 定義幫助類庫,DataSetHelper數據集操做,CrystalReportHelper水晶報表幫助類,WmiHelper操做系統WMI幫助類,加密與解密幫助類RSACryptionHelper,SafeInvokeHelper 用於COM操做幫助類,數據庫操做幫助類SqlHelper,StatisticsHelper數據統計幫助類,StrongNameSignatureHelper強命名驗證幫助類。
  • FTP文件傳輸 System.Net.FtpClient,這個引用於netftp,有不少例子代碼可快速入手。
  • 類型轉換 Type Converter,在設計ASP.NET控件的時候會常常遇到這個類型,用於將ASPX中的文本定義轉化爲.NET類型,比較經常使用的如bool值轉換,0轉換爲false,1或其它值轉化爲true,字符Y轉化true,字符N轉化爲false,MSDN中不少TypeConverter的例子能夠參考。
  • Excel導入類,對於Excel導入類,對功能的惟一的要求是不能必定要求安裝Microsoft Excel,客戶的服務器中能夠安裝的軟件很是少,因此全盤否認微軟自帶的Office Interop。
  • 定義系統經常使用的資源文件,所有以嵌入的資源內置在程序集中。

 

2. Component 公共控件與組件

  • Editor 編輯控件,文本編輯控件TextEditor, 日期編輯控件DateTimeEditor,下拉選擇控件ComboEditor,多行明細數據編輯控件Grid,單選控件CheckBoxEditor,圖片編輯控件PictureBox,富文本編輯控件RichTextBoxEditor,數字編輯控件NumericEditor,時間編輯控件TimeEditor,甘特圖編輯控件GanttaEditor。
  • Calendar日期控件  日期控件用於顯示當前時間範圍內的任務(工做單,生產計劃,送貨計劃),可參考Outlook中的日期控件,代碼來自於CodeProject中的文章。
  • Form 窗體基類,這是很核心的部件,子類窗體的代碼可否簡潔高效,全在於這個地方。定義FormBase類型,包含基本的功能:多語言(可讀取界面上全部控件進行Text屬性重設置),佈局可持久化(Layout Persistence),用於將用戶修改過的界面偏號保存,經常使用於Grid列順序修改,SplittContainer上下面板位置大小調整,自定義佈局(Custom Layout) 用於窗體設計器修改界面佈局,窗體快捷鍵定義,好比將Enter鍵重寫成Tab鍵方便跳轉。
  • Query Form/Enquiry Form 查詢窗體基類,用於定義通用查詢界面,用戶將一個SQL語句,或存儲過程,或是經過查詢生成工具生成一個查詢,經過這個界面基類解析產生界面和產數據。
  • Crystal Report Form 水晶報表基類,用戶設計完報表,放置到配置的目錄中,便可查看水晶報表,方便打印設定,報表多語言,報表參數傳遞,報表導出爲Excel或PDF,報表生成爲指定格式發送到用戶郵件。
  • Error Dialog 異常對話框,CodeProject中有一篇文章是講解如何獲取.NET堆棧的信息,當系統業務拋出異常時,須要將此異常信息封裝,好比獲取當前程序的版本,構建時間等封裝傳遞到異常對話框,在異常對話框中點一個簡單的複製到剪貼版按鈕便可將出錯的信息收集起來,這樣方便程序員診斷問題。
  • Form Designer 窗體設計器,用於自定義佈局Layout,修改以後將佈局保存爲Xml文件,FormBase會預先在自定義佈局表(FormLayout)中搜索此功能的佈局定義,如發現有則加載。.NET CLR Form Host中有文章介紹如何生成Xml文件定義的內容,簡單的理解能夠將Visual Studio定義爲一個代碼生成工具,拖放控件到窗體中會生成不一樣的源代碼,C#,VB.NET,還有Xml,Visual Studio不支持生成Xml格式界面配置,但CLR Form Host能夠實現這一點。
  • Graph 圖表基類 用於以圖表的方式呈現數據,柱子圖/餅圖/點狀圖/曲線圖/K線圖,打開Excel的圖表功能便可看到各類類型的圖表,Visual Studio 2009內置了豐富的圖表控件,進行簡單的封裝便可。
  • Field Range Control 查詢組件 涉及到ORM的查詢,只須要給這個控件填寫到實體名稱和屬性名稱,它便可爲我生成查詢條件,這樣在設計時很方便設計查詢條件,節省了大量的拼接條件的代碼。
  • Condition Editor 條件編輯控件,主要用於工做流中的IF-ELSE活動的條件編輯。
  • BackgroundWorker 多線程組件,用於多線程處理,.NET系統已經包含很實用的後臺線程控件BackgroundWorker,避免主界面卡死,也實現了多線程處理,可是這個控件須要依託在Form窗體中,須要增長一個WorkerThreadBase,參考Code Project中的文章。
  • Misc 雜項 SQL編輯器控件,系統中好比生成查詢語句,工做流的條件設置,預警提醒的查詢語句等地方會涉及到SQL顯示或書寫,有一個語法高亮的編輯控件會給系統增色很多,Code Project上有大量的SQL Hightlight Editor控件可供使用,Auto CAD圖紙顯示控件,工程模塊的物料清單可能會增長圖紙附件,須要聯機在線查看DWG格式的圖紙,桌面提醒控件 Desktop Alert 這個的參考例子是MSN的消息提醒,Outlook新郵件到時的提醒,參考Code Project上有許多相似控件。Tab MDI佈局控件(DockManager),這個組件也至關重要,因Infragistics中就有一個這樣的組建,開箱即用,能夠將傳統的MDI佈局改爲Tab MDI,不須要修改代碼。圖表控件Image Control用於給圖片設定縮放模式,攝像頭控件,用於人事系統中的員工主檔給員工拍攝相片,瀏覽器控件Web Browser用於顯示網頁,重寫.NET系統提供的控件,修改幾個屬性,關閉錯誤腳本提示。

 

3. 預約義基礎功能 Administration UI

設計精良的系統應該先預約義好一系列的基礎界面,用於管理框架功能中的元數據,這一節分兩個部分講解,一是框架要定義什麼,二是如何去實現這些功能。先來看一下框架數據庫Framework有哪些基礎的元數據表定義:性能優化

先寫一個基礎查詢語句,用於查詢框架系統數據庫的全部表。服務器

SELECT * FROM sys.tables ORDER BY name
數據表 定義
Attachment 系統中全部功能的附件,可直接存儲文件或是存放一個FTP文件路徑

Branch / BranchDetail多線程

實現多庫存組織
Company 實現多公司賬套
Configuration 系統參數配置

ContextFunction ContextFunctionDetail架構

系統上下文菜單項定義

Dictionary
DictionaryDetail框架

可變的數據字典定義,用於可修改的數據字典

FormLayout
FormLayoutDetail編輯器

自窗義界面(Form Designer設計以後保存的Xml文件)
FormProfile 用戶偏號(網格排序,控件位置或大小拖動)
LanguageTranslation 多國語言翻譯
Component 系統啓動時讀取的程序集
Lookup 查找數據對話框
Message
MessageDetail
消息盒子
Report 報表參數定義
ScheduledTask 系統預置的計劃任務
SystemModule
SystemFunction
系統包含的模塊與功能
User 系統用戶
UserDefinedQuery 預約義查詢
UserGroup 用戶組別
UserGroupAuthorization 用戶組別受權
UserGroupMenu 用戶組別菜單
UserGroupMenuBitmap 用戶組別導航圖
UserLog 用戶日誌
Workflow 工做流定義

 

  • 可修改的數據字典,好比員工工做等級,從T1到T4,再到M1,T表示Technican技術員,M表示Manaer經理,這些均可以根據實現須要增減。不可修改的數據字典如性員Gender,只有Male或Female兩種選項,不能修改,這種不可變的數據字典直接用代碼寫死。
  • 系統預置的計劃任務,經常使用於工做流中的消息提醒或報表生成需求。前者如當庫存不夠時發送消息提醒採購人員,後者用於每週按期生成老闆報表發送到老闆郵箱中。
  • 工做流定義保存工做流設計器生成的XOML文件。Visual Studio不支持生成XOML格式的工做流定義,但.NET Workflow Host可經過修改輸出獲取工做流設計器生成的工做流定義文件。
  • 單據編碼/單據序列號 有的客戶偏好於放在業務數據庫中,在上表中沒有提到。

經過上面框架數據庫表的定義便可看到框架的基礎功能,也就是對以上數據進行讀寫。我按照窗體的類別簡單介紹。

  1. 登入退出類功能:LoginDialog用戶登入,登入成功後可顯示Splash Screen,以後進入主界面Main Form,用戶退出時,還要檢測當前是否有窗體的數據沒有保存(dirty)逐個提醒用戶保存數據或是放棄修改,用戶可能會修改登入密碼,用戶也可能作一些菜單或功能的自定義。
  2. 設計類功能:Query Designer 設計查詢,將查詢文本保存到數據表UserDefinedQuery中。Report Dialog Designer用於維護報表參數,報表的設計由水晶報表設計完成,實在沒有精力去維護一個Report Designer,因此直接用功能強大的水晶報表,在報表對話框中只須要維護報表的參數,這樣不用寫代碼便可完成將參數值傳遞到報表中。Workflow Designer用於設計工做流,保存結果XOML到Workflow表中。Form Designer用於修改自定義佈局,隱藏或調整控件位置,或修改查詢條件。Lookup Designer 用於設計查找窗體,直觀的解釋是當光標放到客戶編號控件中時,此控件會顯示一個小按鈕,點擊按鈕會彈出客戶編號選擇對話框,這裏的設計查找窗體,也就是設計這個客戶編號選擇對話框。
  3. 應用程序類功能:控制應用程序的啓動,關閉,控制通訊層,實現Application Recovery模式,這個功能能夠從Windows 7 Code Package中獲取源代碼參考。當應用程序崩潰時,能夠提示從新啓動再恢復崩潰前的數據。
  4. 自動更新類功能:支持從FTP,HTTP,XCOPY等方式下載最新版本的文件更新系統。目前沒有實現調用微軟的Background Intelligent Transfer Service,也沒有實現調用第三方下載API的功能,不支持斷點續傳或是快速的大文件下載。調用迅雷API速度很快的緣由多是要求服務器中有備份文件,這對於企業應用來講不可行,另外第三方的下載API會遭遇限速等困擾,仍是老老實實的實現局域網內的快速穩定更新。
  5. 通用附件類功能:實現一個通用的附件管理模塊,其它功能只須要設置一個SupportAttachment=true屬性便可擁有附件管理功能。附件可保存在數據庫或FTP文件服務器中。

 

4 工做流基礎 Workflow Essential

工做流實現的四大基礎功能:通知提醒,批覈,計劃任務,調用自定義代碼。

通知提醒:ERP系統中包含大量的提醒功能,每加一個業務功能就寫一遍提醒功能的代碼調用顯得有些繁瑣,在此只作一個設置便可實現通知設置,包括要通知的人員,通知的內容。

批覈:框架應該抽象出全部單據的批覈需求,創建一個獨立的批覈系統,任何功能只須要簡單設置一下便可調用工做流代碼,實現批覈流程。

計劃任務: 系統中有一些按期執行的任務,好比員工生日提醒,庫存餘額報警,待收貨記錄提醒,老闆報表定時發送。

調用自定義代碼:若是系統中的功能存在缺陷defect,軟件公司不肯意修改的狀況下,能夠考慮增長自定義的.NET代碼解決問題。只須要在合理的事件點上插入合適代碼,完成重複的數據修復工做。

 

基於微軟工做流的解決方案,先看一下包含的基礎組件:

Activities 活動庫,活動是工做流定義中一個基本的代碼執行單元,可固化執行的代碼都可封裝到一個活動中。包含文檔批覈活動,發送報表活動,查詢活動,調用.NET代碼活動等。調用.NET代碼活動的設定方法參考以下:

assembly=Microsoft.Applications.MyReportDll;
class=Microsoft.Applications.MyReportDll.EmployeelistingDAL;
method=GetEmployeeListing();
 

熟悉.NET框架反射調用方法的朋友一看就明白上面定義的含義,這個活動的源代碼能夠簡化以下所示:

protected override ActivityExecutionStatus Execute(ActivityExecutionContext executionContext)
{ 
     assembly = Assembly.Load(segments[0]);
     type = assembly.GetType(segments[1]);
     method = segments[2];

      type.GetMethod(method, BindingFlags.Public | BindingFlags.Static).Invoke(null, null);
}
 

Contracts 接口與實現 在第一步活動定義中,大量的調用了WF中的CallExternalMethod活動,這個活動用於調用外部自定義方法,實現接口與實現的分離。在設計活動時只須要指定要調用的接口和方法,具體的實現可根據須要變化。

.NET WF要求在啓動WF Runtime時,須要先註冊要執行的服務,代碼參考以下:

SqlWorkflowPersistenceService  persistenceService=new SqlWorkflowPersistenceService  (ConnectionString);
runtime.AddService(persistenceService);
 

在活動的代碼中,可經過如下的方式引用通過註冊的服務:

SqlWorkflowPersistenceService  persistenceService=context.GetService<SqlWorkflowPersistenceService>();
//調用 persistenceService服務的方法

這樣,服務中可調用ERP代碼的接口,實現了ERP邏輯與.NET WF工做流的整合。

 

Workflows 給每種常見的流程定義一個工做流類型,方便作持久化和驗證工做。

Workflow Designer Control re-host工做流定義組件,直接參考借用MSDN中的例子。

Monitor 工做流監控,查看流程的執行狀況,當前執行結點,執行路徑。

 

5 服務器體系 Server Series

從功能上來說,系統應該具有如下四個基礎服務器,實現數據讀寫分離。

Application Server  業務邏輯服務器,.NET Remoting服務器端。

Report Server 報表服務器,用於報表呈現,減低Application Server的壓力。

Workflow Server 工做流服務器 執行工做流。

Scheduling Server 計劃任務服務器,減低Application Server的壓力。

每種服務器都配置Console版和Service版,代碼徹底同樣,Console以控制檯程序呈現,Service以Windows 服務應用形式實現,前者方便開發,後者用於部署和實際使用。

 

Application 應用程序

根據ERP項目的功能分類,分爲進銷存(Distribution),工程(Engineering),生產(Production),生產計劃(Production Planning),財務(Account Receivable,Account Payable,General Ledger),客戶關係(CRM)等模塊。每一個模塊獨立爲一個Visual Studio Project,編譯成一個程序集。經過插件式結構,實現使用時只須要在Component表中插入一行記錄,便可讓系統識別到此程序集,運用反射方法調用程序集中的功能。

1 業務實體與業務邏輯 Business Logic

若是是用LLBL Gen Pro開發系統,則業務實體層具有如下文件夾層次結構。

image

以銷售單表頭爲例子,數據庫表SalesOrder,生成實體爲SalesOrderEntity,設計讀寫接口文件爲ISalesOrderManager, 接口的實現類爲SalesOrderManager,用簡單的圖表示以下:

SalesOrder –> SalesOrderEntity –> ISalesOrderManager –> SalesOrderManager

系統強制執行以上約定,而且設計了Code Smith模板代碼生成來減小出錯的可能。既提供強制性約束,又提供工具輔助開發人員遵照約定,系統開發效率成倍提高。

業務實體層還實現了數據審計(Audit)功能,記錄表的每一個記錄的修改值。剛畢業參加工做時,經常混淆Audit和Approval的區別,如今一些系統還存在用Audit做爲批覈的意義。

 

2  數據字典 Enum

定義系統中不可變的數據字典,雖然用代碼寫死字典的方法值得商議,但它的好處也是很是明顯的。

定義一個勞動合同的枚舉,分固按期限和無固按期限的合同,參考下面的代碼。

public enum ContractType
{
        [StringValue("F")]
        [DisplayText("Fixed Time")]
        FixedTime,

        [StringValue("U")]
        [DisplayText("Unlimited Time")]
        UnlimitedTime
}

獲取它的值用以下方法,值用於存儲到數據庫中或程序代碼使用:

StringEnum<ContractType>.GetStringValue(ContractType.FixedTime)

獲取它的描述用以下方法,描述用於界面中呈現:

StringEnum<ContractType>.GetDisplayText(ContractType.FixedTime)
  
 

3 業務實現 Business Logic Implementation

一部分邏輯在Business Logic中實現,好比類型初始化值,自動帶值,值驗證等邏輯。複雜的邏輯好比進出倉,涉及到的關聯表會多一些,可能要扣減庫存,修改物料庫存餘額,批號生成,生成出倉平均單價等,複雜的邏輯要單獨放在一個項目中設計源代,這樣方便維護。

   

4 報表 Report

從形式上來分,分爲圖形報表和數據報表。圖形報表用微軟.NET 自帶的圖形控件完成,MSDN上包含Samples Environments for Microsoft Chart Controls的大量例子。數據報表用水晶報表完成,600多個水晶報表文件,涵蓋單據的打印,列表查詢打印,主檔數據打印等類別。豐富的水晶報表功能爲系統增色很多。

 

5  系統維護 System Maintenance

集成一些經常使用的功能,不須要進入系統便可完成系統維護。好比數據庫升級,數據庫備份,數據庫還原,新賬套建立,系統參數設定,數據庫性能優化(主要是索引重建),這些實用工具程序減輕了系統管理員的負擔。

 
 

6  功能模塊/界面  Presentation

Distribution 進銷存,包含銷售,採購,倉庫模塊。

模塊 功能
Sales  銷售 銷售合同,銷售訂單,送貨,退貨,銷售包裝,銷售發票
Purchasing 採購 採購申請,採購訂單,採購收貨,採購退貨,供應商發票
Inventory 倉庫 進倉(Receipt),出倉(Issue),轉倉(Transfer),盤點(Cycle-count)

Engineering  工程  物料清單,標準成本設定。

Production   生產  工做單,工做單發料,倒衝與組裝,物料退回,發散料。

Production Planning 生產計劃 主生產計劃MPS,物料需求計劃MRP, 能力需求計劃CRP

Finance 財務  Account Receivable應收,Account Payable應付,General Ledger總賬。

CRM  客戶關係 銷售線索,銷售日報,銷售月報,出差申請與費用報銷。

 

在個人從業經歷以來,我認爲搭建一套開發框架對企業開發是頗有用處的。前期所花費的精力和時間在後期都會獲得充分的回報。然而搭建框架所花費的時間和精力,值得商榷。公司一直都是對股東負責,能用最少的時間作完項目,收回合同款便可,大費周折的去作產品基礎功能,對於小公司而言生存都是問題,精心設計的框架須要大量的精力去維護和改善,拋開公司因素,學習一個大型系統對我的的職業發展和成長也是至關重要的。

相關文章
相關標籤/搜索