ERP程序開發中遇到的六種錯誤

常常回顧同事寫的代碼,發現一些問題,總結分析,用於員工培訓,或系統優化方面的內容教學。css

文中有問題的的代碼我用黑體字標識。html

1 界面與邏輯代碼混淆

這是目前發現的比較嚴重的問題。框架花費了很大的力氣,運用數據綁定,就是爲了讓界面(控件操做)與後臺邏輯(驗證與傳值)執行相對嚴格的分離。這裏我只能說相對嚴格的分離,由於後臺中一些操做不可避免的須要在前臺提示用戶確認,或是提示用戶輸入一些變量值,這部分邏輯也可能會參與在前臺界面中。我舉例以下。數據庫

private void grid_AfterCellUpdate(object sender, CellEventArgs e)
{         
            if (this.gridUom.ActiveCell == null || !this.gridUom.ActiveCell.IsDataCell)
                return;

            ItemEntity Ientity = itemBindingSource.Current as ItemEntity;
            ItemAuxiLiaryEntity itemAuxiLiaryEntity = gridUom.GetRowListObject(gridUom.ActiveRow) as ItemAuxiLiaryEntity;
            if (gridUom.ActiveRow != null)
            {
                if (BaseCommon.StringCompare(e.Cell.Column.Key, "AuxiLiaryDefault") == 0)
                {
                   
                    List<int> indices = entity.ItemAuxiLiaries.FindMatches(ItemAuxiLiaryFields.AuxiLiaryDefault == true & ItemAuxiLiaryFields.Uom != itemAuxiLiaryEntity.Uom);
                    if (indices.Count > 0)
                    {
                        ItemAuxiLiaryEntity customerEntity = entity.ItemAuxiLiaries[indices[0]] as ItemAuxiLiaryEntity;
                        customerEntity.AuxiLiaryDefault = false;
                     }
             }
}

這段代碼有如下幾個問題緩存

1 AfterCellUpdate事件徹底能夠放到後臺業務邏輯類中,由於這裏只是作業務操做操做,並不涉及到用戶確認或輸入數據或用戶通知的行爲,能夠概括的說,除了這三種特殊類型的操做以外(用戶確認,輸入數據,用戶通知)的數據變動,均可以放置到後臺業務實體中完成。框架

2 性能:這裏通過了屢次數據轉化調用(as操做符),它的性能不太好。並且列名的判斷太遲,每次對Grid的單元格的操做都會觸發兩次數據轉化(as操做符)行爲。性能

這類XX_Changed,XX_Updated,儘可能將代碼遷移到後臺邏輯中。一是爲了維護,二是改善性能。優化

2  事件的不恰當運用

Closing事件是正在關閉時發生,尚未關閉,這時能夠取消,阻止事件冒泡。Closed是關閉完成,能夠作一些其它的資源釋放操做。理解這兩個事件的區別,有助於合理應用事件。參考下面的代碼this

private void chbSuspended_CheckedChanged(object sender, EventArgs e)
 {
            if (chbSuspended.Checked)
            {
                if (!string.IsNullOrEmpty(txtItemNo.Text))
                {
                   
                    IPurchaseOrderManager PurchaseOrderManager = ClientProxyFactory.CreateProxyInstance<IPurchaseOrderManager>();
                    if (PurchaseOrderManager.IsPurchaseOrderExist(bucket))
                    {
                        DialogResult Result = BaseCommon.ShowConfirm("Item is already in used", null, MessageBoxButtons.OKCancel);
                        if (Result != DialogResult.OK)
                        {
                            chbSuspended.Checked = false;
                        }
                    }
從代碼的意圖中咱們能夠看出,這是一個須要用戶確認的操做。當用戶勾選單選框以後,讀取數據判斷是否合理,提示用戶以後將單選框取消選擇。在這裏,咱們徹底能夠把操做放到Validating事件或是Changing事件中,表達這個值改變以前還須要咱們的驗證確認,這樣對系統的性能開銷比較小。若是如上代碼所示,等到值改變完成,控件刷新完成以後,再把它還原到未改變以前的狀態,這樣的性能很差。
 

3 應該考慮用空間換時間的性能改善方案

簡單的說,就是把值提早計算好並保存起來,在用的時候直接讀取值以取代頻繁的計算。這種狀況出現的概率對高,我作幾處說明。
1)主表與從表的關係數據。主表須要保存從表的數據統計。好比銷售訂單表頭有一個Amount金額字段用於保存明細行的金額累總,這就是一個典型的空間換時間的方案。由於讀取表頭的字段發生的頻率過高了,因此咱們不會每次都讀取明細行並累總顯示。
2)基礎數據表與業務表的數據。好比,我要統計某一個商品的採購訂單數量累總,銷售訂單數量累總,生產任務單數量累總。咱們經常使用的方法是,要用到這些累總時,直接去讀取單據數據。而我這裏推薦的是空間換時間的方案。作單據業務時,將業務單據的數據提早保存到基礎數據表中。再具體來講,就是qty_on_order(商品銷售訂單數量),qty_on_jo(商品生產訂單數量)等累總字段增長到物料表中,在作業務單據時更新物料表相應字段的值。
3)業務數據表的分析表。好比咱們銷售送貨單,會建立兩張表(Shipment/ShipmentDetail)記錄此數據。爲此,咱們還須要提供大量的查詢以知足各類業務場景。這時就能夠考慮將建立新的數據表來存儲相關的查詢結果,好比未送貨/未完成訂單,須要綜合訂單表或送貨表來多緯度的查詢,按客戶,按銷售員,按項目等。這個項目中,會產生比較多的Balance,Journal,Summary等數據表。
 

4 合理利用緩存可改善系統效率

對於一些不常改變的數據項,在實施階段就固定下來的基礎數據,咱們能夠考慮在系統登入前緩存到系統數據字典中,這樣在讀取數據時可顯示改善效率。一些常有的基礎數據,好比單位,貨幣,銷售員,會計賬戶,考慮將它們加入到系統緩存中。如用戶更改這些數據項,須要更新緩存中的數據項。
缺乏了這項考慮,系統就會出現頻繁的從各個基礎數據表中讀取數據,給系統的效率帶來負擔。

 

5 缺乏對數據庫NULL值的處理

對於數量單價類的字段值,它是直接從用戶界面中獲取,而對於平均單價,最後一次進倉單價,它們的值由系統計算得出。這就會形成前者與後者數據的產生時機不一致,二者爲空值NULL的狀況會比較多。因而下面的查詢過濾條件經常是沒有做用的。
IRelationPredicateBucket bucket=...
bucket.PredicateExpression.Add(SalesOrderDetailFields.Qty > SalesOrderDetailFields.DeliveryQty);

對於字符串的字段,null和string.Empty是不一樣的,在數據庫中,NULL和空字符串也是不一樣的。字符的全角半角也應該控制好。
spa

6 啓動窗體時載入數據項過多

儘可能使用延遲加載數據的模式,而避免啓動界面時及時加載全部的數據項。這條規則比較明顯的地方是界面中有過多的DropDownList或ComboBox。若是肯定要使用這類控件,應該將它的數據項載入時間延遲到控件展開時完成(數據綁定優於逐個數據項增長)。參考這裏(http://stackoverflow.com/questions/2901371/lazy-loading-wpf-combobox-items)。code

相關文章
相關標籤/搜索