簡體   English   中英

層體系結構的最佳實踐是什么?

[英]What is the best practice for layer architecture?

現在,我正在研究一個用VB6開發的大型銀行解決方案。 該應用程序是基於表單的大型應用程序,缺少分層的體系結構(用於數據訪問,業務邏輯和表單操作的所有代碼都在單個表單類中)。 我現在的工作是重構此代碼。 我正在用C#編寫適當的業務邏輯層和數據訪問層,並且該表單將保留在VB中。

以下是代碼片段:

public class DistrictDAO
{
    public string Id{get;set;}
    public string DistrictName { get; set; }
    public string CountryId { get; set; }
    public DateTime SetDate { get; set; }
    public string UserName { get; set; }
    public char StatusFlag { get; set; }
}

地區實體類,為什么擴展名為DAO,我不清楚。

 public class DistrictGateway
{
    #region private variable
    private DatabaseManager _databaseManager;
    #endregion

    #region Constructor
    public DistrictGateway(DatabaseManager databaseManager) {
        _databaseManager = databaseManager;
    }
    #endregion

    #region private methods
    private void SetDistrictToList(List<DistrictDAO> dataTable, int index, DistrictDAO district){
        // here is some code for inserting 
    }    
    #endregion

    #region public methods
        try
        {
        /*
         query and rest of the codes
         */    

        }
        catch (SqlException sqlException)
        {
            Console.WriteLine(sqlException.Message);
            throw;
        }
        catch (FormatException formateException)
        {
            Console.WriteLine(formateException.Message);
            throw;
        }
        finally {
            _databaseManager.ConnectToDatabase();
        }


    public void InsertDistrict() { 
        // all query to insert object
    }

    public void UpdateDistrict() { 

    }
    #endregion
}

負責數據庫查詢處理的DistrictGateway類現在是業務層。

  public class District
{
    public string Id { get; set; }
    public string DistrictName { get; set; }
    public string CountryId { get; set; }
}


public class DistrictManager
{
    #region private variable
    private DatabaseManager _databaseManager;
    private DistrictGateway _districtGateway;
    #endregion

    #region Constructor
    public DistrictManager() { 
        // Instantiate the private variable using utitlity classes
    }
    #endregion

    #region private method
    private District TransformDistrictBLLToDL(DistrictDAO districtDAO) { 

        // return converted district with lots of coding here
    }

    private DistrictDAO TransformDistrictDLToBLL(District district)
    {

        // return converted DistrictDAO with lots of coding here
    }

    private List<District> TransformDistrictBLLToDL(List<DistrictDAO> districtDAOList)
    {

        // return converted district with lots of coding here
    }

    private List<DistrictDAO> TransformDistrictDLToBLL(List<District> district)
    {

        // return converted DistrictDAO with lots of coding here
    }


    #endregion

    #region public methods
    public List<District> GetDistrict() {
        try
        {
            _databaseManager.ConnectToDatabase();
          return TransformDistrictBLLToDL(  _districtGateway.GetDistrict());

        }
        catch (SqlException sqlException)
        {
            Console.WriteLine(sqlException.Message);
            throw;
        }
        catch (FormatException formateException)
        {
            Console.WriteLine(formateException.Message);
            throw;
        }
        finally {
            _databaseManager.ConnectToDatabase();
        }
    }

    #endregion

這是業務層的代碼。

我的問題是:

  1. 它是一個完美的設計嗎?
  2. 如果沒有,這里有什么缺陷?
  3. 我認為,此代碼具有重復的try catch塊
  4. 對於此實現,什么是好的設計

完善? 沒有這樣的事。 如果您必須在這里提問,那可能是錯誤的。 即使現在“完美”,也不會一次出現,並且熵會抓住它。

當需要擴展它時,將衡量您的表現如何。 如果您的更改能夠順利進行,則說明您做得很好。 如果您感覺要與遺留代碼抗爭以添加更改,請找出您做錯了什么並進行重構。

瑕疵? 很難說。 我現在沒有足夠的精力,時間或動力去深入挖掘。

無法弄清楚#3的意思。

典型的分層如下所示,其中的箭頭顯示了依賴性:

view <- controller -> service +-> model <- persistence  (service knows about persistence)

每層都有跨領域的關注點:

  • 視圖知道有關表示,樣式和本地化的信息。 它會盡一切可能改善用戶體驗的驗證,但不包括業務規則。
  • 控制器與視圖緊密相連。 它關心從視圖綁定和驗證請求,路由到適當的服務,錯誤處理以及路由到下一個視圖。 而已。 業務邏輯屬於服務,因為您希望它與Web,平板電腦,移動設備等相同。
  • 服務是業務邏輯賴以生存的地方。 它擔心根據業務規則進行驗證,並與模型和持久層協作以實現用例。 它知道用例,工作單元和事務。
  • 如果您更喜歡功能性樣式,則模型對象可以是值對象;如果您願意,則可以使用更豐富的業務邏輯。
  • 持久性隔離所有數據庫交互。

如果使用像Spring這樣的框架,它包含面向方面的編程,則可以將諸如安全性,事務,監視,日志記錄等跨領域關注點視為方面。

雖然,您實際上並沒有在問一個具體的問題,但似乎您可能只需要一些一般性指導即可使您走上正確的道路。 由於我們沒有像您一樣對整個應用程序有深入的了解,因此為您提出一種單一的方法可能很奇怪。

最近,n層體系結構似乎是一個熱門問題,但它激發了我在其上撰寫博客系列的文章。 檢查這些SO問題和博客文章。 我認為他們會大大幫助您。

N層架構博客系列(帶有示例代碼)

對於大型項目,我建議使用MVVM模式,這樣您就可以完全測試您的代碼,以后再擴展它或更改它的部分將變得更加容易。 即使您將能夠更改UI,而無需更改其他層中的代碼。

如果您的工作是重構代碼,那么首先請您的老板詢問您是否真的應該重構它為其添加功能。 在這兩種情況下,您都需要圍繞該代碼的自動測試工具。 如果幸運的話,您應該為其添加功能,那么您至少有一個起點和一個目標。 否則,您將不得不自己選擇起點並且沒有目標。 您可以無限地重構代碼。 沒有目標可能會令人沮喪。

在不測試災難的情況下重構代碼而無需測試。 重構代碼意味着在不改變其行為的情況下改進其結構。 如果不進行任何測試,則不能確定沒有破壞任何東西。 由於您需要定期進行大量測試,因此這些測試必須自動化。 否則,您將花費太多時間進行手動測試。

遺留代碼很難放入某些測試工具中。 您將需要對其進行修改才能使其可測試。 您將測試包裝在代碼周圍的工作將隱式導致代碼的某些分層結構。

現在出現了雞蛋問題:您需要重構代碼才能對其進行測試,但是現在您還沒有測試。 答案是從“防御性”重構技術開始並進行手動測試。 您可以在Micheal Feather的書《有效地使用舊版代碼》中找到有關這些技術的更多詳細信息。 如果您需要重構大量的遺留代碼,則應該真正閱讀它。 這是一個真正的大開眼界。

對您的問題:

  1. 沒有完美的設計。 只有潛在的更好的。
  2. 如果應用程序沒有任何單元測試,那么這是最大的缺陷。 首先介紹測試。 另一方面:這些代碼片段一點也不壞。 看來, DistrictDAO類似的技術版本District 也許有人試圖引入某些領域模型。 並且:至少DistrictGateway會將DatabaseManager注入為構造函數參數。 我見過更糟。
  3. 是的,try-catch塊可以看作是代碼重復,但這並不稀奇。 您可以嘗試通過明智地選擇Exception類來減少catch子句。 或者,您可以使用委托或某些AOP技術,但這會使代碼的可讀性降低。 有關更多信息,請參見其他問題
  4. 使遺留代碼適合某些測試工具。 更好的設計將隱含地出現。

無論如何:首先要弄清楚老板對重構代碼的含義。 僅在沒有目標的情況下重構代碼是沒有效果的,也不會使老板滿意。

暫無
暫無

聲明:本站的技術帖子網頁,遵循CC BY-SA 4.0協議,如果您需要轉載,請注明本站網址或者原文地址。任何問題請咨詢:yoyou2525@163.com.

 
粵ICP備18138465號  © 2020-2024 STACKOOM.COM