2009-04-22 54 views
2

我有一個相當特殊的數據源,我必須使用它(實際上是一個會計應用程序的接口)。雖然它非常強大,但我必須通過很多箍環來獲取我想要的數據。例如,如果我想獲取表的內容並指定應該返回哪些列,則必須遍歷.Columns集合並將.SetVisible()調用到我想要的列。DSL vs方法調用:利弊

目前我們有一種方法可以解決這個問題,並允許我們以更簡單的方式指定事物,但該函數的參數列表正在快速增長,並且大多數時候我們只需要指定其中的一些當我們稱它時。總之 - 這是一個僵化的解決方案。

說來我首先想到的解決辦法是這樣的:

DataTable result = DataSourceWrapper.StartQuery("TableName") 
    .SetVisibleColumns("Col1", "Col2", "Col3") 
    .SetCriteria("CriteriaName", "Param1Name", CriteriaParam1, "Param2Name", CriteriaParam2) 
    .SetFilter("Col4 = ? AND Col5 = ?", FilterParam1, FilterParam2) 
    .SetReportParams("Param1Name", ReportParam1, "Param2Name", ReportParam2) 
    .Execute(); 

標準,過濾器和ReportParams一些特定於應用程序的事情,我不會在這裏討論它們。但總的想法是這樣的。這與調用方法幾乎類似,只不過您可以選擇要指定的參數(通過調用特定的方法)並獲得更多的IntelliSense幫助。你也可以玩方法調用的順序。

請注意,SetFilter()有一個解析表達式。這是DataSource難以處理的另一件事 - 它可以很好地處理表達式,但是必須將它們作爲特殊對象的樹來傳遞,而這些對象的寫入時間又相當長。在previous question我要求幫助解析這樣的表達式。當前的包裝器方法有一個自制表達式解析器,它可以解析簡單的表達式,但是我想讓它們的支持更完整。

在該問題中,建議使用Irony項目。檢查出來後,我決定確實適合這種需求。但是過了一會兒,我發現,它比這更強大。爲什麼不讓我自己的查詢語言完全適合這項任務?然後上面會看起來像:

DataTable result = DataSourceWrapper.Query(@" 
    SELECT Col1, Col2, Col3 
    FROM TableName 
    WITH CRITERIA CriteriaName(Param1Name={0}, Param2Name={1}) 
    WITH REPORTPARAMS (Param1Name={2}, Param2Name={3} 
    WHERE Col4 = {4} AND Col5 = {5}", 
    CriteriaParam1, CriteriaParam2, 
    ReportParam1, ReportParam2, 
    FilterParam1, FilterParam2 
); 

但是...這不是一個矯枉過正的?這兩種方法的優缺點是什麼?我看到的是:

臨DSL:

  • 查詢更簡潔;

Pro的方法:

  • 更多的IntelliSense支持;方法名稱/參數名稱(和註釋)不需要文檔(DSL將不得不被徹底記錄);
  • 可能會更快創建?我從來沒有創建自己的DSL,所以我不知道這是多少工作。反諷似乎要承擔我肩上的很多負擔,但還剩下多少呢?

增加:爲了澄清,這兩種方法將只被編碼器使用。外部人員和業務分析員不會使用它。

回答

2

你必須小心你所說的DSL。請參閱Martin Fowler's Bliki post on DSL。您的方法鏈接示例非常接近內部DSL。稍微修改它,它是:

DataTable result = DataSourceWrapper.Query("TableName") 
    .With(new Columns("Col1", "Col2", "Col3")) 
    .Where(new AndCritera("CriteriaName", 
     new Criterion("Param1Name", CriteriaParam1), 
     new Criterion("Param2Name", CriteriaParam2)) 
    .Filter(
     new Filter("Col4").Equals(FilterParam1), 
     new Filter("Col5").Equals(FilterParam2)) 
    .With(
     new ReportParam("Param1Name", ReportParam1), 
     new ReportParam("Param2Name", ReportParam2)); 

話雖這麼說,這仍然是C#領域內非常多,只有程序員將能夠編寫這些查詢。如果您的要求促使您向非程序員提供查詢,那麼您可能會考慮按照您在第二個示例中指定的方式創建外部DSL。

+0

不,這隻會用於我們程序員的內部使用。而且,是的 - 這正是我的觀點。我非常接近實際的DSL,下一步就是實現它。這樣做的關鍵在於讓代碼更容易編寫,所以DSL在這方面比較有成就(它比你在這裏寫的更短),但是我擔心的是創建它需要多長時間。也許還有其他的障礙,我不知道。 – 2009-04-22 18:49:01

0

我會選擇DSL方法。

原因: 1這是更接近領域的專家,從個人的經驗,像在DSL形式的東西BAS的,它打破了商業頭腦的人與開發商之間的溝通障礙,使得編寫技術規範更容易 2通過使用像Irony這樣的工具,你的DSL將被很好地定義,並且是測試驅動開發的一個很好的候選者。3實現DSL確實需要開發人員進行一些初始學習(我使用的是javacc,它比Irony更友好),但一旦你掌握了這些想法,它變得很容易,而且你的代碼變得非常通用,因爲你可以將邏輯卸載到DSL中。