代碼要恰如其分——記一次代碼審查

代碼要恰如其分,說的是隻實現當前須要的功能,保留必定的可擴展性,但不要爲了在很長一段時間內都不會發生的事情實現可擴展性。
不要預測未來,未來的新需求能夠經過不斷的重構來保持代碼的健康和可擴展性。web

下面是一個在WCF內部服務中實現的類,這個前提很重要,這是一個服務的內部實現,不是契約,是不須要對外發布的組件(不含服務契約,契約經過另外的組件發佈)。ide

 1 public static class PictureRecognizerFactory
 2     {
 3         private static PictureRecognizer[] m_Recognizers;
 4         private static object _oSync = new object();
 5 
 6         private static PictureRecognizer[] m_AllRecognizers
 7         {
 8             get
 9             {
10                 if (m_Recognizers == null)
11                 {
12                     lock (_oSync)
13                     {
14                         if (m_Recognizers == null)
15                         {
16                             m_Recognizers = FindAllPictureRecognizer();
17                         }
18                     }
19                 }
20                 return m_Recognizers;
21             }
22         }
23 
24         /// <summary>
25         /// 獲取圖片的類別
26         /// </summary>
27         /// <param name="picture"></param>
28         /// <returns></returns>
29         public static PictureType GetPictureType(Picture picture)
30         {
31             foreach (PictureRecognizer item in m_AllRecognizers)
32             {
33                 PictureType type = item.Reconize(picture);
34                 if (type != PictureType.Unknown)
35                     return type;
36             }
37             return PictureType.Unknown;
38 
39         }
40 
41         /// <summary>
42         /// 尋找全部被標識了PictureRecognizerAttribute的類
43         /// </summary>
44         /// <returns></returns>
45         private static PictureRecognizer[] FindAllPictureRecognizer()
46         {
47             Type[] typesWithRecognizer = GetTypesWithRecognizers();
48 
49             List<PictureRecognizer> list = new List<PictureRecognizer>();
50             foreach (Type type in typesWithRecognizer)
51             {
52                 list.Add((PictureRecognizer)type.Assembly.CreateInstance(type.FullName));
53             }
54 
55             return list.ToArray();
56         }
57 
58         /// <summary>
59         /// 獲取全部標記爲RecognizerAttribute的類型
60         /// </summary>
61         /// <returns></returns>
62         private static Type[] GetTypesWithRecognizers()
63         {
64             List<Type> typesRecognizers = new List<Type>();
65             Assembly[] assemblies = AppDomain.CurrentDomain.GetAssemblies();
66             foreach (Assembly ass in assemblies)
67             {
68                 try
69                 {
70                     Type[] types = ass.GetTypes();
71                     foreach (Type type in types)
72                     {
73                         if (type.GetCustomAttributes(typeof(PictureRecognizerAttribute), true).Length > 0)
74                         {
75                             typesRecognizers.Add(type);
76                         }
77 
78                     }
79                 }
80                 catch { }//若是在某個Assembly中加載不到類型,則不予理會,不處理異常
81             }
82             if (typesRecognizers.Count == 0)
83                 throw new Exception("找不到任何圖像識別器");
84             return typesRecognizers.ToArray();
85         }
86     }
View Code

這段代碼有幾個問題:spa

一、它經過AppDomain.CurrentDomain.GetAssemblies()來獲取當前加載的全部程序集,也就是做者認爲會有不少類被標記了PictureRecognizerAttribute。實際上,正如咱們前提條件所說,PictureRecognizerAttribute是一個在非公開發布的服務組件中定義的類,它是屬於服務的內部實現機制,在能夠預見的未來都不須要發佈給服務外部的類使用。所以,全部定義了PictureRecognizerAttribute的類都和PictureRecognizerAttribute在同一個程序集中。這點很是重要。代碼規範

二、基於第一個前提,也就是說全部被標記爲PictureRecognizerAttribute的類對PictureRecognizerFactory都是可見的,而且可能被標記爲PictureRecognizerAttribute類數量很是少,所以經過New來實現是最簡單、高效的。code

三、實際上程序須要獲取的是繼承至PictureRecognizer的實現類,所以應該直接判斷類型是否繼承至PictureRecognizer,無需經過判斷PictureRecognizerAttribute,引入一個無用的類。blog

重構之後的代碼:繼承

 1 public static class PictureRecognizerFactory
 2     {
 3         static readonly PictureRecognizer[] _Recognizers = new PictureRecognizer[] 
 4         { 
 5             new PictureRecognizerImpl1(),
 6             new PictureRecognizerImpl2(),
 7         };
 8 
 9         /// <summary>
10         /// 獲取圖片的類別
11         /// </summary>
12         /// <param name="picture"></param>
13         /// <returns></returns>
14         public static PictureType GetPictureType(Picture picture)
15         {
16             foreach (PictureRecognizer item in _Recognizers)
17             {
18                 PictureType type = item.Reconize(picture);
19                 if (type != PictureType.Unknown)
20                     return type;
21             }
22             return PictureType.Unknown;
23 
24         }
25     }
View Code

 若是未來須要必定的開放程度,能夠經過暴露內部集合來增長必定的擴展性,參考 Asp.Net MVC ViewEngines 類的實現。圖片

不要對將來作過多(不是不要)的設想,保持代碼的精簡,增長代碼的可讀性、可維護性是軟件開發過程當中很是重要的一點。代碼的行數越少,可能發生的Bug就越少,未來的維護(重構、擴展)難度就越低。開發

本篇文章不討論類的命名,代碼規範等問題,若有此類問題請忽略。: )get

相關文章
相關標籤/搜索