注:虽然是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后的函数来决定。