代碼閱讀性 是我提出來的概念, 首創可是沒有版權。特地和代碼可讀性區別開來;更增強調業務概念而不是技術名詞。 現給出一個極端的標準: sass
若是一行代碼, 不能5秒鐘內看出它的功能,咱們能夠說這段代碼的閱讀性不佳。 框架
如下這段代碼,是個人依賴注入框架中的一小段代碼。 測試
private readonly IDictionary<Type, resolver> item_resolvers; public IEnumerable<Interface> get_all<Interface>() { var type = typeof (Interface); foreach (var pair in item_resolvers) { if (type.IsAssignableFrom(pair.Key)) yield return (Interface) pair.Value.resolve(); } }
首先,介紹一下背景:這個方法get_all<Interface>()是從依賴注入容器中獲得全部實現了指定接口<Interface>的對象實例。忽略細節,這個方法的核心是循環容器中每個的類解析器,比較該類是否實現或繼承了指定的接口。 this
第6行if (type.IsAssignableFrom( pair.Key ))判斷實現或繼承用到了C#的一個方法,IsAssignableFrom()這裏是微軟對該方法的定義。摘自: http://msdn.microsoft.com/ZH-cn/library/system.type.isassignablefrom.aspx code
public virtual bool IsAssignableFrom(Type c) orm
若是 c 和當前 Type 表示同一類型,當前 Type 在 c 的繼承層次結構中,當前 Type 是 c 實現的接口,c 是泛型類型參數且當前 Type 表示 c 的約束之一,或 c 表示值類型且當前 Type 表示 Nullable(Visual Basic 中的 Nullable(Of c)),則爲 true。 若是不知足上述任何一個條件或者 c 爲 null,則爲 false。 對象
即便看完了幫助文字,有誰知道,這個方法兩邊的類型,哪一個是子類,哪一個是父類? blog
對那些知道的人,我想說:恭喜你,你已經不是正常人了。我至今仍然沒記住,到底哪裏個是哪一個。 繼承
這個方法名是一個典型的實現命名法,我猜測,它的內部的實現機制,可能就是判斷一個類型是賦值過另外一個類型。而做爲該功能用戶的我,如前面的背景所述,想知道,是誰繼承了誰。所以: 接口
首先,脫離開剛纔的產品代碼,咱們對咱們創造的新方法作一個剝離,剝離到哪去,到測試中去。
public class TypeExtensionsSpecs { class base_class { } class child_class : base_class { } private It the_class_is_not_inheried_from_itself = () => typeof(base_class).is_inherited_from(typeof(base_class)).ShouldBeFalse(); private It the_base_class_is_not_inheried_from_its_child_class = () => typeof(base_class).is_inherited_from(typeof(child_class)).ShouldBeFalse(); private It the_child_class_is_not_inheried_from_its_base_class = () => typeof(child_class).is_inherited_from(typeof(base_class)).ShouldBeTrue(); }
請先忽略那些與測試框架相關的龍套代碼,如It甚至Lambda表達式, 若是有時間,後面的主題能夠專門講講行爲測試框架MSpec。這裏我定義了兩個類,一個子類。很明顯,個人測試就是預期,子類是基類的子類,嗯有點繞口,但不管是我口頭的描述,仍是很是近似的測試代碼描述,是很清楚明白的,是否是不到5秒能徹底看懂?
public static bool is_inherited_from(this Type type, Type base_type) { return !(type == base_type) && base_type.IsAssignableFrom(type); }
即算作了n遍,到這個實現代碼我幾乎仍然是拼湊以期讓測試經過,由於我實在是弄出清楚IsAssignableFrom的方向性。只有測試讓我更清楚些。
技術上,沒有別的,主要用到了.Net的新特性 Extension
說新其實也不新了。至少我都用了三、5年了。我想這個名稱應該來源於所謂的開閉原則,對修改關閉,對擴展開放,這就是一個擴展功能,仍是名副其實。
做爲完結咱們看看應用新方法以後的原代碼。是否是好懂不少,也就減小了bug的機會,你想寫反都難!
private readonly IDictionary<Type, resolver> item_resolvers; public IEnumerable<Interface> get_all<Interface>() { var type = typeof (Interface); foreach (var pair in item_resolvers) { /* 新代碼 */ if (pair.Key.is_inherited_from(type)) yield return (Interface) pair.Value.resolve(); } }
恰好,說到這裏,在閱讀性上,咱們這一段代碼還可走的更遠,如用Linq來替換循環和過濾的功能,等等。無論,咱們如今有多不完美,可是至少咱們是朝着正確的方向!
(本文版權屬於© 2012 - 2013 予沁安 | 轉載請註明做者和 出處)