敏捷開發松結對程式設計系列之十四:一些重構而不影響他人的編程訣竅

來源:互聯網
上載者:User

本文是“松結對程式設計”系列的第十三篇。(松結對程式設計欄目目錄)

松結對程式設計包括L型代碼結構的一個很大的問題,是在於由於人們複用了太多的代碼,以至於所有代碼牽一髮而動全身。這很容易導致一個底層庫改動後,很多地方編譯不通過,或編譯通過但運行不通過。

本人曾經擔任過底層庫的編寫者,在修改和維護底層庫的過程中遇到了很多問題,也發現了一些訣竅,下面是一些編碼層級的處理訣竅。這些訣竅其實都寫在教科書上,學習和使用起來也很簡單,只是到用的時候,被很多人忽略了。

1. 預設參數如果要給一個函數增加一個新的變數,因這個變數的不同而產生新的行為方式,那麼預設參數是一個很好的避免之前的代碼需要相應改動的方法。比如:

        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)

這樣初期的、簡單的調用就不用修改。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() + "_"));        }

不過,重載和預設參數之間要做一個平衡,比如上面那個ImageLink,很多參數都是交叉的,就不適合重載。當初曾經想把普通的LInk和AjaxLink分開,但發現分開或不分開,都需要textColor之類的參數,所以後來實際的做法是把裡邊的代碼再行分別建立函數,以減少單個函數的長度。3. 虛函數(多態,virtual,override)虛函數的目的,是為了“讓今天的代碼,調用明天的功能”。當年剛剛聽說虛函數有這麼大本事,大吃一驚。如果你正在擔心明天增加了新的功能,還得修改今天的代碼,那麼肯定就需要求助虛函數了。比如下面這個情境:程式員A正在寫一個顯示各種Notice的介面,而設計“各種Notice”的是B,而且他經常增加新的類型。這時候虛函數就可以派上用場。

    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後的函數來決定。


"為什麼我很少用虛函數?"很可能是用了太多的switch-case所致。如果用switch-case來處理各種notice的顯示結果,那麼就需要通過增加新的分支,來處理新的顯示方法。這個最大的壞處是:剛才說的A和B兩個程式員就要經常交叉工作。而一旦A離職了,B每次增加新的類型,都要去到A的代碼裡邊去改動,極其危險。火星人的11000行代碼中,只有6個switch-case,其中兩個似乎也可以用虛函數避免。
其他的還有很多手段來防止維護代碼影響之前的代碼調用,但這三個是最常用的,可以說在團隊代碼有交叉的時候,每個人都必備上述技能才可能和諧工作。剛開始一般只有師傅具備完全使用上述功能的能力,但隨著徒弟們的能力提升,可以逐步嘗試讓徒弟也掌握這些技能,從而可以協助師傅維護底層庫。

聯繫我們

該頁面正文內容均來源於網絡整理,並不代表阿里雲官方的觀點,該頁面所提到的產品和服務也與阿里云無關,如果該頁面內容對您造成了困擾,歡迎寫郵件給我們,收到郵件我們將在5個工作日內處理。

如果您發現本社區中有涉嫌抄襲的內容,歡迎發送郵件至: info-contact@alibabacloud.com 進行舉報並提供相關證據,工作人員會在 5 個工作天內聯絡您,一經查實,本站將立刻刪除涉嫌侵權內容。

A Free Trial That Lets You Build Big!

Start building with 50+ products and up to 12 months usage for Elastic Compute Service

  • Sales Support

    1 on 1 presale consultation

  • After-Sales Support

    24/7 Technical Support 6 Free Tickets per Quarter Faster Response

  • Alibaba Cloud offers highly flexible support services tailored to meet your exact needs.