監(jiān)理公司管理系統(tǒng) | 工程企業(yè)管理系統(tǒng) | OA系統(tǒng) | ERP系統(tǒng) | 造價咨詢管理系統(tǒng) | 工程設(shè)計管理系統(tǒng) | 甲方項目管理系統(tǒng) | 簽約案例 | 客戶案例 | 在線試用
X 關(guān)閉

erp軟件開發(fā)常見問題

申請免費試用、咨詢電話:400-8352-114

   經(jīng)?;仡櫷聦懙拈_發(fā)代碼,發(fā)現(xiàn)一些問題,總結(jié)分析,用于員工培訓(xùn),或系統(tǒng)優(yōu)化方面的內(nèi)容教學(xué)。

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

  1 界面與邏輯代碼混淆

  這是目前發(fā)現(xiàn)的比較嚴重的問題??蚣芑ㄙM了很大的力氣,運用數(shù)據(jù)綁定,就是為了讓界面(控件操作)與后臺邏輯(驗證與傳值)執(zhí)行相對嚴格的分離。這里我只能說相對嚴格的分離,因為后臺中一些操作不可避免的需要在前臺提示用戶確認,或是提示用戶輸入一些變量值,這部分邏輯也可能會參與在前臺界面中。我舉例如下。

  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 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事件完全可以放到后臺業(yè)務(wù)邏輯類中,因為這里只是做業(yè)務(wù)操作操作,并不涉及到用戶確認或輸入數(shù)據(jù)或用戶通知的行為,可以歸納的說,除了這三種特殊類型的操作之外(用戶確認,輸入數(shù)據(jù),用戶通知)的數(shù)據(jù)變更,都可以放置到后臺業(yè)務(wù)實體中完成。

  2 性能:這里經(jīng)過了多次數(shù)據(jù)轉(zhuǎn)化調(diào)用(as操作符),它的性能不太好。而且列名的判斷太遲,每次對Grid的單元格的操作都會觸發(fā)兩次數(shù)據(jù)轉(zhuǎn)化(as操作符)行為。

  這類XX_Changed,XX_Updated,盡量將代碼遷移到后臺邏輯中。一是為了維護,二是改善性能。

  2 事件的不恰當運用

  Closing事件是正在關(guān)閉時發(fā)生,還沒有關(guān)閉,這時可以取消,阻止事件冒泡。Closed是關(guān)閉完成,可以做一些其它的資源釋放操作。理解這兩個事件的區(qū)別,有助于合理應(yīng)用事件。參考下面的代碼

  private void chbSuspended_CheckedChanged(object sender, EventArgs e)

  {

  if (chbSuspended.Checked)

  {

  if (!string.IsNullOrEmpty(txtItemNo.Text))

  {

  IPurchaseOrderManager PurchaseOrderManager = ClientProxyFactory.CreateProxyInstance();

  if (PurchaseOrderManager.IsPurchaseOrderExist(bucket))

  {

  DialogResult Result = BaseCommon.ShowConfirm("Item is already in used", null, MessageBoxButtons.OKCancel);

  if (Result != DialogResult.OK)

  {

  chbSuspended.Checked = false;

  }

  }

  從代碼的意圖中我們可以看出,這是一個需要用戶確認的操作。當用戶勾選單選框之后,讀取數(shù)據(jù)判斷是否合理,提示用戶之后將單選框取消選擇。在這里,我們完全可以把操作放到Validating事件或是Changing事件中,表達這個值改變之前還需要我們的驗證確認,這樣對系統(tǒng)的性能開銷比較小。如果如上代碼所示,等到值改變完成,控件刷新完成之后,再把它還原到未改變之前的狀態(tài),這樣的性能不好。

  3 應(yīng)該考慮用空間換時間的性能改善方案

  簡單的說,就是把值提前計算好并保存起來,在用的時候直接讀取值以取代頻繁的計算。高,我做幾處說明。

  1)主表與從表的關(guān)系數(shù)據(jù)。主表需要保存從表的數(shù)據(jù)統(tǒng)計。比如銷售訂單表頭有一個Amount金額字段用于保存明細行的金額累總,這就是一個典型的空間換時間的方案。因為讀取表頭的字段發(fā)生的頻率太高了,所以我們不會每次都讀取明細行并累總顯示。

  2)基礎(chǔ)數(shù)據(jù)表與業(yè)務(wù)表的數(shù)據(jù)。比如,我要統(tǒng)計某一個商品的采購訂單數(shù)量累總,銷售訂單數(shù)量累總,生產(chǎn)任務(wù)單數(shù)量累總。我們常用的方法是,要用到這些累總時,直接去讀取單據(jù)數(shù)據(jù)。而我這里推薦的是空間換時間的方案。做單據(jù)業(yè)務(wù)時,將業(yè)務(wù)單據(jù)的數(shù)據(jù)提前保存到基礎(chǔ)數(shù)據(jù)表中。再具體來說,就是qty_on_order(商品銷售訂單數(shù)量),qty_on_jo(商品生產(chǎn)訂單數(shù)量)等累總字段增加到物料表中,在做業(yè)務(wù)單據(jù)時更新物料表相應(yīng)字段的值。

  3)業(yè)務(wù)數(shù)據(jù)表的分析表。比如我們銷售送貨單,會創(chuàng)建兩張表(Shipment/ShipmentDetail)記錄此數(shù)據(jù)。為此,我們還需要提供大量的查詢以滿足各種業(yè)務(wù)場景。這時就可以考慮將創(chuàng)建新的數(shù)據(jù)表來存儲相關(guān)的查詢結(jié)果,比如未送貨/未完成訂單,需要綜合訂單表或送貨表來多緯度的查詢,按客戶,按銷售員,按項目等。這個項目中,會產(chǎn)生比較多的Balance,Journal,Summary等數(shù)據(jù)表。

  4 合理利用緩存可改善系統(tǒng)效率

  對于一些不常改變的數(shù)據(jù)項,在實施階段就固定下來的基礎(chǔ)數(shù)據(jù),我們可以考慮在系統(tǒng)登入前緩存到系統(tǒng)數(shù)據(jù)字典中,這樣在讀取數(shù)據(jù)時可顯示改善效率。一些常有的基礎(chǔ)數(shù)據(jù),比如單位,貨幣,銷售員,會計帳戶,考慮將它們加入到系統(tǒng)緩存中。如用戶更改這些數(shù)據(jù)項,需要更新緩存中的數(shù)據(jù)項。

  缺少了這項考慮,系統(tǒng)就會出現(xiàn)頻繁的從各個基礎(chǔ)數(shù)據(jù)表中讀取數(shù)據(jù),給系統(tǒng)的效率帶來負擔。

  5 缺少對數(shù)據(jù)庫NULL值的處理

  對于數(shù)量單價類的字段值,它是直接從用戶界面中獲取,而對于平均單價,最后一次進倉單價,它們的值由系統(tǒng)計算得出。這就會造成前者與后者數(shù)據(jù)的產(chǎn)生時機不一致,兩者為空值NULL的情況會比較多。于是下面的查詢過濾條件常常是沒有作用的。

  IRelationPredicateBucket bucket=...

  bucket.PredicateExpression.Add(SalesOrderDetailFields.Qty > SalesOrderDetailFields.DeliveryQty);

  對于字符串的字段,null和string.Empty是不同的,在數(shù)據(jù)庫中,NULL和空字符串也是不同的。字符的全角半角也應(yīng)該控制好。

  6 啟動窗體時載入數(shù)據(jù)項過多

  盡量使用延遲加載數(shù)據(jù)的模式,而避免啟動界面時及時加載所有的數(shù)據(jù)項。這條規(guī)則比較明顯的地方是界面中有過多的DropDownList或ComboBox。如果確定要使用這類控件,應(yīng)該將它的數(shù)據(jù)項載入時間延遲到控件展開時完成(數(shù)據(jù)綁定優(yōu)于逐個數(shù)據(jù)項增加)。

發(fā)布:2021-05-10 14:01    編輯:泛普軟件 · hujian    [打印此頁]    [關(guān)閉]
相關(guān)文章:
使用說明
聯(lián)系方式

成都公司:成都市成華區(qū)建設(shè)南路160號1層9號

重慶公司:重慶市江北區(qū)紅旗河溝華創(chuàng)商務(wù)大廈18樓

咨詢:400-8352-114

加微信,免費獲取試用系統(tǒng)

QQ在線咨詢