注:雖然是javascript, 但想法對其它語言也適用。
松結對編程包括L型代碼結構的一個很大的問題,是在於由於人們複用了太多的代碼,以至於所有代碼牽一髮而動全身。這很容易導致一個底層庫改動後,很多地方編譯不通過,或編譯通過但運行不通過。
本人曾經擔任過底層庫的編寫者,在修改和維護底層庫的過程中遇到了很多問題,也發現了一些訣竅,下面是一些編碼級別的處理訣竅。這些訣竅其實都寫在教科書上,學習和使用起來也很簡單,只是到用的時候,被很多人忽略了。
1. 缺省參數
- <SPAN style="FONT-SIZE: 18px"> </SPAN><SPAN style="FONT-SIZE: 14px"> public static MvcHtmlString ImageLink(string text, string url, bool showInNewWindow = false, bool showText = true,
- bool showImage = true, string title = null, string outerLink = null,
- string imgUrl = null, string imgSuffix = "16.png",
- string imgCssClass = "icons", string updateTargetId = null,
- string display = null,
- string onSuccess = null, bool runOnSuccessWhileLeft = false,
- string id = null, string imgStyle = null, string cssClass = null,
- string textColor = null,
- bool displayAsText = false, string displayAsTextSuffix = null, string displayAsLinkSuffix = null,
- WebViewPage returnTo = null, string returnUrl = null)</SPAN><SPAN style="FONT-SIZE: 18px">
- </SPAN>
public static MvcHtmlString ImageLink(string text, string url, bool showInNewWindow = false, bool showText = true,
bool showImage = true, string title = null, string outerLink = null,
string imgUrl = null, string imgSuffix = "16.png",
string imgCssClass = "icons", string updateTargetId = null,
string display = null,
string onSuccess = null, bool runOnSuccessWhileLeft = false,
string id = null, string imgStyle = null, string cssClass = null,
string textColor = null,
bool displayAsText = false, string displayAsTextSuffix = null, string displayAsLinkSuffix = null,
WebViewPage returnTo = null, string returnUrl = null)
這個被維護過無數次甚至有點過度設計的函數,能顯示爲文字鏈接,能自動搜索圖標,能作爲在Ajax連接使用,能根據當前值選擇顯示爲文字還是鏈接……但最樸素的用法,始終保持爲Text和Url兩個參數,比如:- @MFCUI.ImageLink(item.Title, "/MFC/Items/Edit?id=" + item.ID)
@MFCUI.ImageLink(item.Title, "/MFC/Items/Edit?id=" + item.ID)
這樣初期的、簡單的調用就不用修改。2. 重載或重寫一個函數
- public static IEnumerable<Product> ProductsAccessibleToUser(string user)
- {
- var productsAccessibleToUser = new List<Product>();
- foreach (var teamID in Department.TeamsContainUser(user).Select(i => i.ID).ToList())
- {
- productsAccessibleToUser.AddRange(ProductsAccessibleToTeam(teamID));
- }
- return productsAccessibleToUser.Distinct();
- }
- public static IEnumerable<int> ProductsAccessibleToUserIDs(string userName)
- {
- return ProductsAccessibleToUser(userName).Select(i => i.ID);
- }
- public static string ProductsAccessibleToUserIDsString(string userName)
- {
- return ProductsAccessibleToUserIDs(userName).Aggregate<int, string>(null, (current, id) => current + (id.ToString() + "_"));
- }
public static IEnumerable<Product> ProductsAccessibleToUser(string user)
{
var productsAccessibleToUser = new List<Product>();
foreach (var teamID in Department.TeamsContainUser(user).Select(i => i.ID).ToList())
{
productsAccessibleToUser.AddRange(ProductsAccessibleToTeam(teamID));
}
return productsAccessibleToUser.Distinct();
}
public static IEnumerable<int> ProductsAccessibleToUserIDs(string userName)
{
return ProductsAccessibleToUser(userName).Select(i => i.ID);
}
public static string ProductsAccessibleToUserIDsString(string userName)
{
return ProductsAccessibleToUserIDs(userName).Aggregate<int, string>(null, (current, id) => current + (id.ToString() + "_"));
}
不過,重載和缺省參數之間要做一個平衡,比如上面那個ImageLink,很多參數都是交叉的,就不適合重載。當初曾經想把普通的LInk和AjaxLink分開,但發現分開或不分開,都需要textColor之類的參數,所以後來實際的做法是把裏邊的代碼再行分別建立函數,以減少單個函數的長度。
3. 虛函數(多態,virtual,override)
- public class NoticeItemAssigned : Notice
- {
- public override MvcHtmlString Information(string user)
- {
- var result = base.Information(user).ToString();
- result = result.Replace("[P1]", UDCValue.ShowAsUsersLink(P1).ToString());
- result = result.Replace("[P2]", UDCValue.ShowAsUsersLink(P2).ToString());
- return new MvcHtmlString(result);
- }
- }
public class NoticeItemAssigned : Notice
{
public override MvcHtmlString Information(string user)
{
var result = base.Information(user).ToString();
result = result.Replace("[P1]", UDCValue.ShowAsUsersLink(P1).ToString());
result = result.Replace("[P2]", UDCValue.ShowAsUsersLink(P2).ToString());
return new MvcHtmlString(result);
}
}
比如上面的NoticeItemAssigned及其他類型的Notice,要顯示它們的Information,都只需要調用@notice.Information(user);但至於顯示出來的結果是什麼,則由其override後的函數來決定。