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

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

申請(qǐng)免費(fèi)試用、咨詢電話:400-8352-114

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

  文中有問(wèn)題的的代碼我用黑體字標(biāo)識(shí)。

  1 界面與邏輯代碼混淆

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

  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;

  }

  }

  }

  這段代碼有以下幾個(gè)問(wèn)題

  1 AfterCellUpdate事件完全可以放到后臺(tái)業(yè)務(wù)邏輯類中,因?yàn)檫@里只是做業(yè)務(wù)操作操作,并不涉及到用戶確認(rèn)或輸入數(shù)據(jù)或用戶通知的行為,可以歸納的說(shuō),除了這三種特殊類型的操作之外(用戶確認(rèn),輸入數(shù)據(jù),用戶通知)的數(shù)據(jù)變更,都可以放置到后臺(tái)業(yè)務(wù)實(shí)體中完成。

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

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

  2 事件的不恰當(dāng)運(yùn)用

  Closing事件是正在關(guān)閉時(shí)發(fā)生,還沒有關(guān)閉,這時(shí)可以取消,阻止事件冒泡。Closed是關(guān)閉完成,可以做一些其它的資源釋放操作。理解這兩個(gè)事件的區(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;

  }

  }

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

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

  簡(jiǎn)單的說(shuō),就是把值提前計(jì)算好并保存起來(lái),在用的時(shí)候直接讀取值以取代頻繁的計(jì)算。高,我做幾處說(shuō)明。

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

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

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

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

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

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

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

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

  IRelationPredicateBucket bucket=...

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

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

  6 啟動(dòng)窗體時(shí)載入數(shù)據(jù)項(xiàng)過(guò)多

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

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

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

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

咨詢:400-8352-114

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

QQ在線咨詢